Number reversal game

From Rosetta Code
Revision as of 09:45, 6 January 2011 by rosettacode>Pmw57 (→‎{{header|JavaScript}}: Using setTimeout structure as some web browsers don't repaint the screen until finished executing the code)
Task
Number reversal game
You are encouraged to solve this task according to the task description, using any language you may know.

Given a jumbled list of the numbers 1 to 9 that are definitely not in ascending order, show the list then ask the player how many digits from the left to reverse. Reverse those digits, then ask again, until all the digits end up in ascending order.

The score is the count of the reversals needed to attain the ascending order.

Note: Assume the players input does not need extra validation.


C.f: Sorting algorithms/Pancake sort, Pancake sorting.

Ada

<lang ada> with Ada.Text_Io; use Ada.Text_Io; with Ada.Integer_Text_Io; use Ada.Integer_Text_Io; with Ada.Numerics.Discrete_Random;

procedure NumberReverse is

  subtype RandRange is Integer range 1..9;
  type NumArrayType is array (Integer range 1..9) of Integer;

  package RandNumbers is new Ada.Numerics.Discrete_Random(RandRange);
  use RandNumbers;
  G : Generator;
  procedure FillArray (A : in out NumArrayType) is
     Temp : RandRange;
  begin
     A := (others => 0);
     for I in 1..9 loop
        Temp := Random(G);
        while A(Temp) /= 0 loop
           Temp := Random(G);
        end loop;
        A(Temp) := I;
     end loop;
  end FillArray;

  procedure Put(A : in NumArrayType) is
  begin
     for I in 1..9 loop
        Put(A(I), 0);
        Put(" ");
     end loop;
  end Put;

  procedure Prompt (Index : out Integer) is
  begin
     New_Line;
     Put("How many numbers would you like to reverse: ");
     Get(Index);
  end Prompt;

  procedure ReverseArray(Arr : in out NumArrayType;
                         Index : in Integer) is
     Temp : RandRange;
  begin
     for I in 1..Index/2 loop
        Temp := Arr(I);
        Arr(I) := Arr(Index + 1 - I);
        Arr(Index + 1 - I) := Temp;
     end loop;
  end ReverseArray;

  Sorted : constant NumArrayType := (1,2,3,4,5,6,7,8,9);
  Arr    : NumArrayType;
  Index  : Integer;
  Count  : Integer := 0;

begin

  Reset(G);
  loop
     FillArray(Arr);
     exit when Sorted /= Arr;
  end loop;
  loop
     Put(Arr);
     Prompt(Index);
     Count := Count + 1;
     ReverseArray(Arr, Index);
     exit when Sorted = Arr;
  end loop;
  Put(Arr);
  New_Line;
  Put("Congratulations! You win. It took " & 
        Integer'Image(Count) & " tries.");

end NumberReverse; </lang>

AutoHotkey

<lang Autohotkey>; Submitted by MasterFocus --- http://tiny.cc/iTunis

ScrambledList := CorrectList := "1 2 3 4 5 6 7 8 9" ; Declare two identical correct sequences While ( ScrambledList = CorrectList )

 Sort, ScrambledList, Random D%A_Space% ; Shuffle one of them inside a While-loop to ensure it's shuffled

Attempts := 0 While ( ScrambledList <> CorrectList ) ; Repeat until the sequence is correct {

 InputBox, EnteredNumber, Number Reversal Game, Attempts so far: %Attempts%`n`nCurrent sequence: %ScrambledList%`n`nHow many numbers (from the left) should be flipped?, , 400, 200
 If ErrorLevel
   ExitApp ; Exit if user presses ESC or Cancel
 If EnteredNumber is not integer
   Continue ; Discard attempt if entered number is not an integer
 If ( EnteredNumber <= 1 )
   Continue ; Discard attempt if entered number is <= 1
 Attempts++ ; Increase the number of attempts
 ; Reverse the first part of the string and add the second part
 ; The entered number is multiplied by 2 to deal with the spaces
 ScrambledList := Reverse(SubStr(ScrambledList,1,(EnteredNumber*2)-1)) SubStr(ScrambledList,EnteredNumber*2)

}

MsgBox, You took %Attempts% attempts to get the correct sequence. ; Final message

Return

-------------------

Reverse(Str) ; Auxiliar function (flips a string) {

 Loop, Parse, Str
   Out := A_LoopField Out
 Return Out

}</lang>

BASIC

Works with: QBasic
Works with: FreeBASIC

<lang qbasic>PRINT "Given a jumbled list of the numbers 1 to 9," PRINT "you must select how many digits from the left to reverse." PRINT "Your goal is to get the digits in order with 1 on the left and 9 on the right."

RANDOMIZE TIMER

DIM nums(1 TO 9) AS INTEGER DIM L0 AS INTEGER, n AS INTEGER, flp AS INTEGER, tries AS INTEGER, again AS INTEGER

'initial values FOR L0 = 1 TO 9

   nums(L0) = L0

NEXT

DO 'shuffle

   FOR L0 = 9 TO 2 STEP -1
       n = INT(RND * (L0)) + 1
       IF n <> L0 THEN SWAP nums(n), nums(L0)
   NEXT
   FOR L0 = 1 TO 8 'make sure it's not in order
       IF nums(L0) > nums(L0 + 1) THEN EXIT DO
   NEXT

LOOP

again = -1 DO

   IF tries < 10 THEN PRINT " ";
   PRINT tries; ":";
   FOR L0 = 1 TO 9
       PRINT nums(L0);
   NEXT
   IF NOT again THEN EXIT DO
   INPUT " -- How many numbers should be flipped"; flp
   IF flp < 0 THEN flp = 0
   IF flp > 9 THEN flp = 0
   FOR L0 = 1 TO (flp \ 2)
       SWAP nums(L0), nums(flp - L0 + 1)
   NEXT
   again = 0
   'check for order
   FOR L0 = 1 TO 8
       IF nums(L0) > nums(L0 + 1) THEN
           again = -1
           EXIT FOR
       END IF
   NEXT
   IF flp > 0 THEN tries = tries + 1

LOOP

PRINT : PRINT "You took "; LTRIM$(RTRIM$(STR$(tries))); " tries to put the digits in order."</lang>

Sample output:

Given a jumbled list of the numbers 1 to 9,
you must select how many digits from the left to reverse.
Your goal is to get the digits in order with 1 on the left and 9 on the right.
  0 : 1  4  5  3  2  7  6  8  9  -- How many numbers should be flipped? 7
  1 : 6  7  2  3  5  4  1  8  9  -- How many numbers should be flipped? 2
  2 : 7  6  2  3  5  4  1  8  9  -- How many numbers should be flipped? 7
  3 : 1  4  5  3  2  6  7  8  9  -- How many numbers should be flipped? 3
  4 : 5  4  1  3  2  6  7  8  9  -- How many numbers should be flipped? 5
  5 : 2  3  1  4  5  6  7  8  9  -- How many numbers should be flipped? 2
  6 : 3  2  1  4  5  6  7  8  9  -- How many numbers should be flipped? 3
  7 : 1  2  3  4  5  6  7  8  9
You took 7  tries to put the digits in order.

C

This example is incorrect. Please fix the code and remove this message.

Details: Example is likely to fail if numbers are initially randomly shuffled to the ordered state. (See talk).

An example of a number reversal game could be: <lang c>void number_reversal_game() { printf("Number Reversal Game. Type a number to flip the first n numbers."); printf("Win by sorting the numbers in ascending order.\n"); printf("Anything besides numbers are ignored.\n"); printf("\t |1__2__3__4__5__6__7__8__9|\n"); int list[9] = {1,2,3,4,5,6,7,8,9}; shuffle_list(list,9);

int tries=0; unsigned int i; int input;

while(!check_array(list, 9)) { ((tries<10) ? printf("Round %d : ", tries) : printf("Round %d : ", tries)); for(i=0;i<9;i++)printf("%d ",list[i]); printf(" Gimme that number:"); while(1) { //Just keep asking for proper input scanf("%d", &input); if(input>1&&input<10) break;

printf("\n%d - Please enter a number between 2 and 9:", (int)input); } tries++; do_flip(list, 9, input); } printf("Hurray! You solved it in %d moves!\n"); }</lang>

Which uses the following helper functions: <lang c>void shuffle_list(int *list, int len) { //We'll just be swapping 100 times. Could be more/less. Doesn't matter much. int n=100; int a=0; int b=0; int buf = 0; //Random enough for common day use.. srand(time(NULL)); while(n--) { //Get random locations and swap a = rand()%len; b = rand()%len; buf = list[a]; list[a] = list[b]; list[b] = buf; } }

void do_flip(int *list, int length, int num) { //Flip a part on an array int swap; int i=0; for(i;i<--num;i++) { swap=list[i]; list[i]=list[num]; list[num]=swap; } }

int check_array(int *arr, int len) {

   while(--len)
   {
       if(arr[len]!=(arr[len-1]+1))
           return 0;
   }
   return 1;

}</lang>

C++

The C code can be used with C++, although the following uses proper C++ iostreams: <lang CPP>void number_reversal_game() { cout << "Number Reversal Game. Type a number to flip the first n numbers."; cout << "You win by sorting the numbers in ascending order."; cout << "Anything besides numbers are ignored.\n"; cout << "\t |1__2__3__4__5__6__7__8__9|\n"; int list[9] = {1,2,3,4,5,6,7,8,9};

       do
       {

shuffle_list(list,9);

       } while(check_array(list, 9));

int tries=0; unsigned int i; int input;

while(!check_array(list, 9)) { cout << "Round " << tries << ((tries<10) ? " : " : " : "); for(i=0;i<9;i++)cout << list[i] << " "; cout << " Gimme that number:"; while(1) { cin >> input; if(input>1&&input<10) break;

cout << "\nPlease enter a number between 2 and 9:"; } tries++; do_flip(list, 9, input); } cout << "Hurray! You solved it in %d moves!\n"; }</lang>

This uses the same helper functions as the C version.

Alternate version using the C++ standard library

This version uses the C++ standard library (note that none of the C helper functions are needed). <lang cpp>

  1. include <iostream>
  2. include <algorithm>
  3. include <functional>
  4. include <iterator>
  5. include <cstdlib>
  6. include <ctime>

template<typename T, int size>

bool is_sorted(T (&array)[size])

{

 return std::adjacent_find(array, array+size, std::greater<T>())
   == array+size;

}

int main() {

 std::srand(std::time(0));
 int list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 do
 {
   std::random_shuffle(list, list+9);
 } while (is_sorted(list));
 int score = 0;
 do
 {
   std::cout << "Current list: ";
   std::copy(list, list+9, std::ostream_iterator<int>(std::cout, " "));
   int rev;
   while (true)
   {
     std::cout << "\nDigits to reverse? ";
     std::cin >> rev;
     if (rev > 1 && rev < 10)
       break;
     std::cout << "Please enter a value between 2 and 9.";
   }
   ++score;
   std::reverse(list, list + rev);
 } while (!is_sorted(list));
 std::cout << "Congratulations, you sorted the list.\n"
           << "You needed " << score << " reversals." << std::endl;
 return 0;

} </lang>

C#

C# 3.0 <lang csharp>using System; using System.Linq;

class Program {

   static void Main(string[] args)
   {
       var r = new Random();
       var tries = 1;
       var sorted = Enumerable.Range(1, 9).ToList();
       var values = sorted.OrderBy(x => r.Next(-1, 1)).ToList();
       while (Enumerable.SequenceEqual(sorted, values)) {
           values = sorted.OrderBy(x => r.Next(-1, 1)).ToList();
       }
       //values = "1 3 9 2 7 5 4 8 6".Split().Select(x => int.Parse(x)).ToList();
       while (!Enumerable.SequenceEqual(sorted, values))
       {
           Console.Write("# {0}: LIST: {1} - Flip how many? ", tries, String.Join(" ", values));
           values.Reverse(0, int.Parse(Console.ReadLine()));
           tries += 1;
       }
       Console.WriteLine("\nYou took {0} attempts to put the digits in order!", tries - 1);
       Console.ReadLine();
   }

}</lang>

C# 1.0 <lang csharp>class Program { static void Main(string[] args) { int[] values = new int[9]; Random tRandom = new Random(); int tries = 0;

for (int x = 0; x < values.Length; x++) { values[x] = x + 1; }

values = RandomPermutation<int>(values);

do { Console.Write("Numbers: "); for (int x = 0; x < values.Length; x++) { Console.Write(" "); Console.Write(values[x]); } Console.WriteLine(". Enter number of numbers from the left to reverse: ");

string tIn = ""; do { tIn = Console.ReadLine(); } while (tIn.Length != 1);

int nums = Convert.ToInt32(tIn.ToString());

int[] newValues = new int[9]; for (int x = nums; x < newValues.Length; x++) { // Move those not reversing newValues[x] = values[x]; } for (int x = 0; x < nums; x++) { // Reverse the rest newValues[x] = values[nums - 1 - x]; } values = newValues; tries++; } while (!check(values));

Console.WriteLine("Success!"); Console.WriteLine("Attempts: " + tries);

Console.Read(); }

public static bool check(int[] p) { // Check all items for (int x = 0; x < p.Length - 1; x++) { if (p[x + 1] <= p[x]) return false; }

return true; }

public static T[] RandomPermutation<T>(T[] array) { T[] retArray = new T[array.Length]; array.CopyTo(retArray, 0);

Random random = new Random(); for (int i = 0; i < array.Length; i += 1) { int swapIndex = random.Next(i, array.Length); if (swapIndex != i) { T temp = retArray[i]; retArray[i] = retArray[swapIndex]; retArray[swapIndex] = temp; } }

return retArray; } }</lang>

Clojure

<lang clojure>(defn flip-at [n coll]

 (let [[x y] (split-at n coll)]
   (concat (reverse x) y )))

(def sorted '(1 2 3 4 5 6 7 8 9))  ; i.e. (range 1 10)

(loop [unsorted (first (filter #(not= % sorted) (iterate shuffle sorted))), steps 0]

 (if (= unsorted sorted)
   (printf "Done! That took you %d steps%n" steps)
   (do
     (println unsorted)
     (printf "Reverse how many? ") 
     (flush)
     (let [flipcount (read)] 
       (recur (flip-at flipcount unsorted), (inc steps))))))</lang>

D

D 2.0 <lang>import std.stdio, std.random, std.string, std.conv, std.algorithm;

void main() {

   int[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
   do {
       randomShuffle(data);
   } while (isSorted(data));
   int trial;
   while (!isSorted(data)) {
       writef("%d: (%s) How many numbers to flip? ", ++trial, data);
       data[0 .. to!int(chomp(readln))].reverse;
   }
   writefln("\nYou took %d attempts.", trial);

}</lang>

F#

This example is incorrect. Please fix the code and remove this message.

Details: Example is likely to fail if numbers are initially randomly shuffled to the ordered state. (See talk).

<lang fsharp>let rand = System.Random() while true do

 let xs = [|for i in 1..9 -> rand.Next(), i|] |> Array.sort |> Array.map snd
 while xs <> Array.sort xs do
   printf "\n%A\n\nReverse how many digits?\n> " xs
   let n = stdin.ReadLine() |> int
   Array.blit (Array.rev xs.[0..n-1]) 0 xs 0 n
 printf "Well done!\n\n"</lang>

Factor

<lang factor>USING: formatting io kernel math math.parser math.ranges namespaces random sequences strings ; IN: rosetta.number-reversal

make-jumbled-array ( -- sorted jumbled )
   CHAR: 1 CHAR: 9 [a,b] [ 1string ] map dup clone randomize
   [ 2dup = ] [ randomize ] while ;

SYMBOL: trials

prompt ( jumbled -- n )
   trials get "#%2d: " printf
   ", " join write
   "   Flip how many? " write flush
   readln string>number ;
game-loop ( sorted jumbled -- )
   2dup = [
       2drop trials get
       "\nYou took %d attempts to put the digits in order!\n" printf
       flush
   ] [
       trials [ 1 + ] change
       dup dup prompt head-slice reverse! drop
       game-loop
   ] if ;
play ( -- )
   0 trials set
   make-jumbled-array game-loop ;</lang>

Forth

This example is incorrect. Please fix the code and remove this message.

Details: Example is likely to fail if numbers are initially randomly shuffled to the ordered state. (See talk).

<lang forth>include random.fs

variable flips create nums 9 cells allot

.array ( addr len -- ) 0 ?do dup @ . cell+ loop drop ;
shuffle ( addr len -- )
 2 swap do
   dup i random cells +
   over @ over @  swap
   rot  ! over !
   cell+
 -1 +loop drop ;
init
 0 flips !
 nums 10 1 do
   i over !  cell+
 loop drop
 nums 9 shuffle
 cr nums 9 .array ;
reverse ( addr len -- )
 1- cells bounds
 begin 2dup >
 while over @ over @ >r over ! over r> swap !
       cell+ swap 1 cells - swap
 repeat 2drop ;
sorted? ( addr len -- )
 1- cells bounds ?do
   i 2@ < if unloop false exit then
 cell +loop true ;
flip ( n -- )
 dup 2 10 within 0= if . ." must be within 2 to 9" exit then
 nums swap reverse
 1 flips +!
 nums 9 sorted? if
   cr ." Got it in " flips @ . ." tries!"
 else
   cr nums 9 .array
 then ;

init 1 2 8 5 7 6 9 4 3 ok 7 flip 9 6 7 5 8 2 1 4 3 ok </lang>

Fortran

Works with: Fortran version 95 and later

<lang fortran>program Reversal_game

 implicit none

 integer :: list(9) = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /)
 integer :: pos, attempts = 0
   
 call random_seed
 do while (sorted(list))
   call Shuffle(list)
 end do
 write(*, "(9i5)") list
 write(*,*)
 do while (.not. Sorted(list))
   write(*, "(a)", advance="no") "How many numbers from the left do you want to reverse? : "
   read*, pos
   attempts = attempts + 1
   list(1:pos) = list(pos:1:-1)
   write(*, "(9i5)") list
   write(*,*)
 end do
 write(*,*)
 write(*, "(a,i0,a)") "Congratulations! Solved in ", attempts, " attempts"

contains

subroutine Shuffle(a)

 integer, intent(inout) :: a(:)
 integer :: i, randpos, temp
 real :: r
 do i = size(a), 2, -1
   call random_number(r)
   randpos = int(r * i) + 1
   temp = a(randpos)
   a(randpos) = a(i)
   a(i) = temp
 end do

end subroutine

function Sorted(a)

 logical :: Sorted
 integer, intent(in) :: a(:)
 integer :: i
 
 do i = 1, size(a)-1
   if(list(i+1) /= list(i)+1) then
     Sorted = .false.
     return
   end if
 end do
 Sorted = .true.

end function

end program</lang>

Groovy

<lang groovy>sorted = [*(1..9)] arr = sorted.clone()

void flipstart(n) { arr[0..<n] = arr[0..<n].reverse() }

int steps = 0 while (arr==sorted) Collections.shuffle(arr) while (arr!=sorted) {

   println arr.join(' ')
   print 'Reverse how many? '
   def flipcount = System.in.readLine()
   flipstart( flipcount.toInteger() )
   steps += 1

} println "Done! That took you ${steps} steps"</lang>

Haskell

Using Rosetta Knuth Shuffle <lang haskell>import Data.List import Control.Arrow import Rosetta.Knuthshuffle

numberRevGame = do

 let goal = [1..9]
 
     shuffle xs =

if xs /= goal then return xs else shuffle =<< knuthShuffle xs

     prefixFlipAt k = uncurry (++). first reverse. splitAt k
     
     prompt r ry = do

putStr $ show r ++ ". " ++ concatMap (flip (++) " ". show) ry ++ " How many to flip? " answ <- getLine let n = read answ if n<10 && 0<n then return n else do putStrLn "Error. The number should be between 0 and 10. Try again" prompt r ry

     playNRG r nrs = 

if nrs == goal then do putStrLn $ "The answer is: " ++ concatMap (flip (++) " ". show) nrs putStrLn $ "It took you " ++ show r ++ " attempts to sort the numbers." putStrLn "" else do answ <- prompt r nrs playNRG (succ r) (prefixFlipAt answ nrs)

 start <- shuffle goal
 
 playNRG 1 start</lang>

Play:

*Main> numberRevGame
1. 3 5 1 4 7 6 8 2 9  How many to flip? 7
2. 8 6 7 4 1 5 3 2 9  How many to flip? 8
3. 2 3 5 1 4 7 6 8 9  How many to flip? 3
4. 5 3 2 1 4 7 6 8 9  How many to flip? 6
5. 7 4 1 2 3 5 6 8 9  How many to flip? 7
6. 6 5 3 2 1 4 7 8 9  How many to flip? 6
7. 4 1 2 3 5 6 7 8 9  How many to flip? 4
8. 3 2 1 4 5 6 7 8 9  How many to flip? 3
The answer is: 1 2 3 4 5 6 7 8 9 
It took you 9 attempts to sort the numbers.

HicEst

<lang HicEst> WRITE(Messagebox) "You took ", Reversals(), " attempts"

FUNCTION Reversals()

 DIMENSION digits(9), temp(9)
 digits = 0
 DO i = 1, 9 ! create the shuffled digits
1   x = CEILING( RAN(9) )
    IF( INDEX(digits, x) ) GOTO 1 ! HicEst has no WHILE
    digits(i) = x
 ENDDO
 DO Reversals = 1, 1E6 ! HicEst needs an upper bound
    DLG(NameEdit=Flips, DNum, MIn=0, MAx=9, Text=digits)
    DO j = 1, Flips/2
       swap = digits(j)
       digits(j) = digits(Flips+1-j)
       digits(Flips+1-j) = swap
    ENDDO
    temp = digits($+1) > digits($) ! $ = left side index
    IF( SUM(temp) == 8 ) RETURN
 ENDDO

END</lang>

Io

<lang io>withRange := method( a, z,

   Range clone setRange(a,z) 

) sorted := withRange(1,9) asList numbers := sorted clone shuffle while( numbers==sorted, numbers = numbers shuffle)

steps :=0 stdin := File standardInput while( numbers != sorted,

   writeln(numbers join(" "))
   write("Reverse how many? ")
   flipcount := stdin readLine asNumber
   withRange(0, ((flipcount-1)/2) floor) foreach( i,
       numbers swapIndices(i,flipcount-1-i)
   )
   steps = steps+1 

) writeln("Done! That took you ", steps, " steps")</lang>

Icon and Unicon

Icon

<lang Icon>procedure main(cq) # Number Reversal Game local x,nums,R,flips

$define PROTECT ["WIN","ASK"] $define MAGIC ["xyzzy","abracadabra","hocus","pocus","presto","changeo","open","sesame","irs"]

put(cq,"game") # start command queue - use command line rule := string(&digits--'0') # ruler and move commands every put(protected := [], map(!PROTECT)) # protected commands every put(magic := [], !MAGIC)

while x := get(cq) | "MOVE" do { # command from queue or ask for move

  case x of {                      
     "help" | "h" | "?" :                                     # --- start of user facing commands ---
        write("Input a position.  The list will be flipped left to right at that point.\n",

"You win when the list is sorted.\n", "Commands:\n",

              "   help, h, ? - shows this\n",
              "   new, g     - new game\n",			   
              "   ruler, r   - shows a ruler\n",
              "   show, s    - shows the list\n",
              "   <n>        - flips the list at ruler position n\n",
              "   quit, q    - quit\n",
              "and various magic words.\n"
              ) & put(cq,"rule")
     "game" | "g" | "new"  : {
        put(cq,"help")                                     
        flips := 0
        nums := rule
        until nums ~== rule do 
        every !nums :=: ?nums                                 # shuffle
        }
     "rule" | "ruler" | "r" : 
        put(cq,"show") & every writes(" " || " " | !(if /mirror then rule else reverse(rule)) | "\n") 
     "show" | "s" :
        every writes(" " || "=" | !nums | " =\n") 
     !rule : {                                                #  0 - 9 for flipping
        if /mirror then nums[1+:x] := reverse(nums[1+:x]) 
        else nums[0-:x] := reverse(nums[0-:x]) 		 
        flips +:= 1
        put(cq,if nums == rule then "WIN" else "show")
        }
     "quit" | "q" : 
        break write("Goodbye.") 
     !magic:                                                  # --- start of magic 
        write("That has no power here.  Try again!") 
     "magic" | "mirror" | "m" : {                        
        mirror := if /mirror then 1 else &null 
        write("Wait! What is this? The writing has reversed.")
        }		   
     !protected:                                              # --- Start of internal (upper case) and protected commands
        put(cq,?rule) & write("Tisk, Tisk, don't try and cheat.  Take a random penalty flip!") 		  
     "MOVE" :                                                  
        put(cq,ask("Command? : ") ) 		 
     "WIN" : 
        put(cq,"ASK") & write("Congratulations you won in ",flips," flips!") 
     "ASK" :
        put(cq,case ask("Play another game? : ") of { "y"|"yes" : "game"; "n"|"no" : "quit"; default : "ASK" } ) 
     default:                                                 # --- say what?
        write("Sorry I don't know that command, try help?")
     }
  }

end

procedure ask(s) #: ask for input with prompt s and return the 1st word in lower case writes(\s) map(trim(read())) ? return tab(upto(' ')|0) end </lang>

Sample output:

Input a position.  The list will be flipped left to right at that point.
You win when the list is sorted.
Commands:
   help, h, ? - shows this
   new, g     - new game
   ruler, r   - shows a ruler
   show, s    - shows the list
   <n>        - flips the list at ruler position n
   quit, q    - quit
and various magic words.

  123456789
 =745361289 =
Command? : 7
 =216354789 =
Command? : 3
 =612354789 =
Command? : 6
 =453216789 =
Command? : 2
 =543216789 =
Command? : 5
Congratulations you won in 5 flips!
Play another game? :

Unicon

The Icon solution works in Unicon.

Inform 7

<lang inform7>Number Reversal Game is a room.

The current list is a list of numbers that varies.

When play begins: now the current list is a shuffled list from 1 to 9; now the command prompt is "Current list: [current list in brace notation].[line break]How many items to flip? ".

Definition: a list of numbers (called L) is sorted: repeat with N running from 1 to the number of entries in L: if entry N in L is not N, no; yes.

To decide which list of numbers is a shuffled list from (min - number) to (max - number): let result be a list of numbers; repeat with N running from min to max: add N to result; while true is true: sort result in random order; if result is not sorted, decide on result.

Flipping is an action applying to one number. Understand "[number]" as flipping.

Carry out flipping: let N be the number understood; let L be the current list; truncate the current list to the first N entries; reverse the current list; truncate L to the last (number of entries in L minus N) entries; add L to the current list.

Report flipping: say "".

Every turn: if the current list is sorted, end the story saying "You have won".

This is the new print final score rule: say "It took you [turn count] flip[s] to sort the list."

The new print final score rule is listed instead of the print final score rule in the for printing the player's obituary rules.</lang>

J

Solution: <lang j>require 'misc' NB. for the verb prompt

INTRO=: noun define Number Reversal Game Flip groups of numbers from the left of the list until the numbers are sorted in ascending order. )

reversegame=: verb define

 whilst. (-: /:~)nums do.
   nums=. 1+9?9                    NB. 1-9 in random order
 end.
 score=. 0
 smoutput INTRO                    NB. Display instructions
 while. -.(-: /:~)nums do.
   score=. 1+ score                NB. increment score
   nnum=. 0".prompt (":score),': ',(":nums),' How many numbers to flip?: '
   if. 0 = #nnum do. return. end.  NB. exit on ENTER without number
   nums=. (C.i.-nnum) C. nums      NB. reverse first nnum numbers
 end.
 'You took ',(": score), ' attempts to put the numbers in order.'

)</lang> Example Usage: <lang j> reversegame Number Reversal Game Sort the numbers in ascending order by repeatedly flipping sets of numbers from the left.

1: 4 7 5 6 9 1 2 8 3 How many numbers to flip?: 5 2: 9 6 5 7 4 1 2 8 3 How many numbers to flip?: 9 3: 3 8 2 1 4 7 5 6 9 How many numbers to flip?: 2 4: 8 3 2 1 4 7 5 6 9 How many numbers to flip?: 8 5: 6 5 7 4 1 2 3 8 9 How many numbers to flip?: 3 6: 7 5 6 4 1 2 3 8 9 How many numbers to flip?: 7 7: 3 2 1 4 6 5 7 8 9 How many numbers to flip?: 5 8: 6 4 1 2 3 5 7 8 9 How many numbers to flip?: 6 9: 5 3 2 1 4 6 7 8 9 How many numbers to flip?: 5 10: 4 1 2 3 5 6 7 8 9 How many numbers to flip?: 4 11: 3 2 1 4 5 6 7 8 9 How many numbers to flip?: 3 You took 11 attempts to put the numbers in order.</lang>

JavaScript

Use knuth_shuffle() function from here.

Works with: Firefox

as well as Internet Explorer, and Chrome <lang html4strict><html> <head>

   <title>Number Reversal Game</title>

</head>

<body>

<script type="text/javascript"></lang> <lang javascript>function endGame(progress) {

   var scoreId = progress.scoreId,
       result = 'You took ' + progress.count + ' attempts to put the digits in order!';
   if (progress.abort === true) {
       result = 'Game aborted.';
   }
   document.getElementById(scoreId).innerHTML = result;

}

function reverseFirstN(arr, n) {

   var reversed = arr.slice(0, n).reverse();
   return reversed.concat(arr.slice(n));

}

function isSorted(arr) {

   return arr.slice(0).sort().toString() === arr.toString();

}

function gameLoop(progress) {

   if (isSorted(progress.arr)) {
       endGame(progress);
   } else {
       var n = parseInt(window.prompt('How many elements to reverse?', ), 10);
       if (isNaN(n)) {
           progress.abort = true;
       } else {
           progress.arr = reverseFirstN(progress.arr, n);

progress.innerHTML += '

' + progress.arr + '

';

           progress.count += 1;
       }
       if (progress.abort !== true) {
           // allow window to repaint before next guess
           setTimeout(function () {
               gameLoop(progress);
           }, 1);
       }
   }

}

function knuth_shuffle(a) {

   var n = a.length,
       r,
       temp;
   while (n > 1) {
       r = Math.floor(n * Math.random());
       n -= 1;
       temp = a[n];
       a[n] = a[r];
       a[r] = temp;
   }
   return a;

}

function playGame(startId, progressId, scoreId) {

   var progress = document.getElementById(progressId);
   progress.arr = knuth_shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9]);

document.getElementById(startId).innerHTML = '

' + progress.arr.toString() + '

';

   progress.count = 0;
   progress.scoreId = scoreId;
   // allow window to repaint before prompting for a guess
   setTimeout(function () {
       gameLoop(progress);
   }, 1);

}

playGame('start', 'progress', 'score');</lang> <lang html4strict></script> </body> </html></lang>

OCaml

This example is incorrect. Please fix the code and remove this message.

Details: Example is likely to fail if numbers are initially randomly shuffled to the ordered state. (See talk).

Imperative

<lang ocaml>let swap ar i j =

 let tmp = ar.(i) in
 ar.(i) <- ar.(j);
 ar.(j) <- tmp

let shuffle ar =

 for i = pred(Array.length ar) downto 1 do
   let j = Random.int (i + 1) in
   swap ar i j
 done

let reversal ar n =

 for i = 0 to pred(n/2) do
   let j = (pred n) - i in
   swap ar i j
 done

let sorted ar =

 try
   let prev = ref ar.(0) in
   for i = 1 to pred(Array.length ar) do
     if ar.(i) < !prev then raise Exit;
     prev := ar.(i)
   done;
   (true)
 with Exit ->
   (false)

let () =

 print_endline "\
 Number Reversal Game
 Sort the numbers in ascending order by repeatedly 
 flipping sets of numbers from the left.";
 Random.self_init();
 let nums = Array.init 9 (fun i -> succ i) in
 shuffle nums;
 let n = ref 1 in
 while not(sorted nums) do
   Printf.printf "#%2d: " !n;
   Array.iter (Printf.printf " %d") nums;
   print_newline();
   let r = read_int() in
   reversal nums r;
   incr n;
 done;
 print_endline "Congratulations!";
 Printf.printf "You took %d attempts to put the digits in order.\n" !n;
</lang>

Functional

<lang ocaml>let revert li n =

 let rec aux acc i = function
 | [] -> acc
 | xs when i <= 0 -> acc @ xs
 | x::xs -> aux (x::acc) (pred i) xs
 in
 aux [] n li

let take li n =

 let rec aux acc i = function
 | x::xs when i = n -> (x, List.rev_append acc xs)
 | x::xs -> aux (x::acc) (succ i) xs
 | _ -> invalid_arg "take"
 in
 aux [] 0 li

let shuffle li =

 let rec aux acc len = function
 | [] -> acc
 | li ->
     let x, xs = take li (Random.int len) in
     aux (x::acc) (pred len) xs
 in
 aux [] (List.length li) li

let rec sorted = function

 | [] -> (true)
 | x::y::_ when x > y -> (false)
 | x::xs -> sorted xs

let () =

 print_endline "\
 Number Reversal Game
 Sort the numbers in ascending order by repeatedly 
 flipping sets of numbers from the left.";
 Random.self_init();
 let li = shuffle [1; 2; 3; 4; 5; 6; 7; 8; 9] in
 let rec loop n li =
   Printf.printf "#%2d: " n;
   List.iter (Printf.printf " %d") li;
   Printf.printf "  ? %!";
   let r = read_int() in
   let li = revert li r in
   if not(sorted li)
   then loop (succ n) li
   else Printf.printf "You took %d attempts to put the digits in order.\n" n;
 in
 loop 1 li
</lang>

Oz

<lang oz>declare

 proc {Main}
    proc {Loop N Xs}
       if {Not {IsSorted Xs}} then
          Num NewXs
       in
          {System.printInfo N#": "}
          {System.print Xs}
          {System.printInfo " -- Reverse how many? "}
          Num = {String.toInt {ReadLine}}
          NewXs = {Append
                   {Reverse {List.take Xs Num}}
                   {List.drop Xs Num}}
          {Loop N+1 NewXs}
       else
          {System.showInfo "You took "#N#" tries to put the digits in order."}
       end
    end
    fun {EnsureShuffled Xs}
       Ys = {Shuffle Xs}
    in
       if {Not {IsSorted Ys}} then Ys
       else {EnsureShuffled Xs}
       end
    end
 in
    {Loop 0 {EnsureShuffled {List.number 1 9 1}}}
 end

 fun {IsSorted Xs}
    {Sort Xs Value.'<'} == Xs
 end

 local
    class TextFile from Open.file Open.text end
    StdIn = {New TextFile init(name:stdin)}
 in
    fun {ReadLine}
       {StdIn getS($)}
    end
 end

 fun {Shuffle Xs}
    {FoldL Xs
     fun {$ Z _}
        {Pick {Diff Xs Z}}|Z
     end
     nil}
 end

 fun {Pick Xs}
    {Nth Xs {OS.rand} mod {Length Xs} + 1}
 end

 fun {Diff Xs Ys}
    {FoldL Ys List.subtract Xs}
 end

in

 {Main}</lang>

Perl

<lang Perl>use List::Util qw(shuffle);

my $turn = 0; my @jumble = shuffle 1..9;

while ( join(, @jumble) eq '123456789' ) {

   @jumble = shuffle 1..9;

}

until ( join(, @jumble) eq '123456789' ) {

   $turn++;
   printf "%2d: @jumble - Flip how many digits ? ", $turn;
   my $d = <>;
   @jumble[0..$d-1] = reverse @jumble[0..$d-1];

}

print " @jumble\n"; print "You won in $turn turns.\n";</lang>

Output:

 1: 9 8 2 5 1 7 6 3 4 - Flip how many digits ? 9
 2: 4 3 6 7 1 5 2 8 9 - Flip how many digits ? 4
 3: 7 6 3 4 1 5 2 8 9 - Flip how many digits ? 7
 4: 2 5 1 4 3 6 7 8 9 - Flip how many digits ? 2
 5: 5 2 1 4 3 6 7 8 9 - Flip how many digits ? 5
 6: 3 4 1 2 5 6 7 8 9 - Flip how many digits ? 2
 7: 4 3 1 2 5 6 7 8 9 - Flip how many digits ? 4
 8: 2 1 3 4 5 6 7 8 9 - Flip how many digits ? 2
    1 2 3 4 5 6 7 8 9
You won in 8 turns.

Perl 6

Do-at-least-once loops are fairly rare, but this program wants to have two of them. We use the built-in .pick(*) method to shuffle the numbers. We use .= to dispatch a mutating method in two spots; the first is just a different way to write ++, while the second of these reverses an array slice in place. The [<] is a reduction operator on less than, so it returns true if the elements of the list are strictly ordered. We also see in the first repeat loop that, although the while condition is not tested till after the loop, the while condition can in fact declare the variable that will be initialized the first time through the loop, which is a neat trick, and not half unreadable once you get used to it.

<lang Perl6>repeat while [<] my @jumbled-list {

   @jumbled-list = (1..9).pick(*)

}

my $turn = 0; repeat until [<] @jumbled-list {

   my $d = prompt $turn.=succ.fmt('%2d: ') ~
                  @jumbled-list ~
                  " - Flip how many digits? "
       or exit;
   @jumbled-list[^$d] .= reverse;

}

say " @jumbled-list[]"; say "You won in $turn turns.";</lang>

Output:

 1: 3 5 8 2 7 9 6 1 4 - Flip how many digits ? 6
 2: 9 7 2 8 5 3 6 1 4 - Flip how many digits ? 9
 3: 4 1 6 3 5 8 2 7 9 - Flip how many digits ? 6
 4: 8 5 3 6 1 4 2 7 9 - Flip how many digits ? 8
 5: 7 2 4 1 6 3 5 8 9 - Flip how many digits ? 7
 6: 5 3 6 1 4 2 7 8 9 - Flip how many digits ? 3
 7: 6 3 5 1 4 2 7 8 9 - Flip how many digits ? 6
 8: 2 4 1 5 3 6 7 8 9 - Flip how many digits ? 4
 9: 5 1 4 2 3 6 7 8 9 - Flip how many digits ? 5
10: 3 2 4 1 5 6 7 8 9 - Flip how many digits ? 3
11: 4 2 3 1 5 6 7 8 9 - Flip how many digits ? 4
12: 1 3 2 4 5 6 7 8 9 - Flip how many digits ? 2
13: 3 1 2 4 5 6 7 8 9 - Flip how many digits ? 3
14: 2 1 3 4 5 6 7 8 9 - Flip how many digits ? 2
    1 2 3 4 5 6 7 8 9
You won in 14 turns.

PicoLisp

<lang PicoLisp>(load "@lib/simul.l")

(de reversalGame ()

  (let (Lst (shuffle (range 1 9))  Cnt 0)
     (while (apply < Lst)
        (setq Lst (shuffle Lst)) )
     (loop
        (printsp Lst)
        (T (apply < Lst) Cnt)
        (NIL (num? (read)))
        (setq Lst (flip Lst @))
        (inc 'Cnt) ) ) )</lang>

Output:

: (reversalGame)
(1 7 6 8 4 2 3 5 9) 4
(8 6 7 1 4 2 3 5 9) 8
(5 3 2 4 1 7 6 8 9) 6
(7 1 4 2 3 5 6 8 9) 7
(6 5 3 2 4 1 7 8 9) 6
(1 4 2 3 5 6 7 8 9) 2
(4 1 2 3 5 6 7 8 9) 4
(3 2 1 4 5 6 7 8 9) 3
(1 2 3 4 5 6 7 8 9) -> 8

PL/I

<lang PL/I> digits: procedure options (main); /* 23 April 2010 */

  declare s character (9) varying;
  declare i fixed binary;
  declare digit character (1);

restart:

  put skip list ('In this game, you are given a group of digits.');
  put skip list ('You will specify one of those digits.');
  put skip list ('The computer will then reverse the digits up to the one you nominate.');
  put skip list ('Your task is to repeat this process a number of times until all the digits');
  put skip list ('are in order, left to right, 1 to 9.');
  put skip list ('Here are your digits');

redo:

  s = ;
  do until (length(s) = 9);
     digit = trim ( fixed(trunc (1+random()*9) ) );
     if index(s, digit) = 0 then s = s || digit;
  end;
  if s = '123456789' then go to redo;

loop:

  do forever;
     put skip list (s);
     if s = '123456789' then leave;
     get edit (digit) (a(1));
     i = index(s, digit);
     if i = 0 then do; put skip list ('invalid request'); iterate loop; end;
     s = reverse( substr(s, 1, i) ) || substr(s, i+1, length(s)-i);
  end;
  put skip list ('Congratulations');
  go to restart;

end digits; </lang>

PureBasic

<lang PureBasic>Dim MyList(9)

Declare is_list_sorted()

If OpenConsole()

 Define score, indata, i, txt$
 
 For i=1 To 9         ;- Initiate the list
   MyList(i)=i
 Next
 While is_list_sorted()
   For i=1 To 9      ;- Do a Fisher–Yates shuffle
     Swap MyList(i), MyList(Random(i)+1)
   Next
 Wend
 
 ;- Start the Game
 Repeat
   score+1
   txt$=RSet(str(score), 3)+": "      ;- Show current list
   For i=1 To 9
     txt$+str(MyList(i))+" "
   Next
   Repeat                             ;- Get input & swap
     Print(txt$+"| How many numbers should be flipped? "): indata=Val(Input())
   Until indata>=1 And indata<=9      ;- Verify the input
   For i=1 To (indata/2)
     Swap MyList(i),MyList(indata-i+1)
   Next
 Until is_list_sorted()
 
 ;- Present result & wait for users input before closing down
 PrintN(#CRLF$+"You did it in "+str(score)+" moves")
 Print("Press ENTER to exit"): Input()
 CloseConsole()

EndIf

Procedure is_list_sorted()

 Protected i
 Shared MyList()
 For i=1 To 9
   If MyList(i)<>i
     ProcedureReturn #False
   EndIf
 Next
 ProcedureReturn #True

EndProcedure</lang>

Python

<lang python> number reversal game

   Given a jumbled list of the numbers 1 to 9
   Show the list.
   Ask the player how many digits from the left to reverse.
   Reverse those digits then ask again.
   until all the digits end up in ascending order.

import random

print(__doc__) data, trials = list('123456789'), 0 while data == sorted(data):

   random.shuffle(data)

while data != sorted(data):

   trials += 1
   flip = int(input('#%2i: LIST: %r Flip how many?: ' % (trials, ' '.join(data))))
   data[:flip] = reversed(data[:flip])

print('\nYou took %2i attempts to put the digits in order!' % trials)</lang>

Sample output:

number reversal game
    Given a jumbled list of the numbers 1 to 9
    Show the list.
    Ask the player how many digits from the left to reverse.
    Reverse those digits then ask again.
    until all the digits end up in ascending order.


# 1: LIST: '1 3 9 2 7 5 4 8 6' Flip how many?: 9
# 2: LIST: '6 8 4 5 7 2 9 3 1' Flip how many?: 6
# 3: LIST: '2 7 5 4 8 6 9 3 1' Flip how many?: 8
# 4: LIST: '3 9 6 8 4 5 7 2 1' Flip how many?: 7
# 5: LIST: '7 5 4 8 6 9 3 2 1' Flip how many?: 3
# 6: LIST: '4 5 7 8 6 9 3 2 1' Flip how many?: 6
# 7: LIST: '9 6 8 7 5 4 3 2 1' Flip how many?: 2
# 8: LIST: '6 9 8 7 5 4 3 2 1' Flip how many?: 4
# 9: LIST: '7 8 9 6 5 4 3 2 1' Flip how many?: 3
#10: LIST: '9 8 7 6 5 4 3 2 1' Flip how many?: 9

You took 10 attempts to put the digits in order!

R

<lang>reversalGame <- function(){

 cat("Welcome to the Number Reversal Game! \n")
 cat("Sort the numbers into ascending order by repeatedly \n",
     "reversing the first n digits, where you specify n. \n \n", sep="")
 # Generate a list that's definitely not in ascending order, per instuctions
 data <- sample(1:9, 9)
 while (all(data == 1:9)){
   cat("What were the chances...? \n")
   data <- sample(1:9, 9)
 }
 trials <- 0
 # Play the game
 while (any(data != 1:9)){
   trials <- trials + 1
   cat("Trial", sprintf("%02d", trials), " # ", data, " #  ")
   answer <- readline(paste("Flip how many? "))
   data[1:answer] <- data[answer:1]  
 }
 
 # Victory!
 cat("Well done.  You needed", trials, "flips. \n")

}</lang>

Sample output: <lang>>reversalGame() Welcome to the Number Reversal Game! Sort the numbers into ascending order by repeatedly reversing the first n digits, where you specify n.

Trial 01 # 4 3 2 1 7 9 8 5 6 # Flip how many? 7 Trial 02 # 8 9 7 1 2 3 4 5 6 # Flip how many? 2 Trial 03 # 9 8 7 1 2 3 4 5 6 # Flip how many? 9 Trial 04 # 6 5 4 3 2 1 7 8 9 # Flip how many? 6 Well done. You needed 4 flips.</lang>

Ruby

<lang ruby>ary = (1..9).to_a ary.shuffle! while ary == ary.sort score = 0 until ary == ary.sort

 print "#{ary.inspect} -- How many digits to reverse? "
 num = gets.to_i  # should validate input
 ary[0, num] = ary[0, num].reverse
 score += 1

end p ary puts "Your score: #{score}"</lang>

sample output:

$ ruby number_reversal_game.rb
[4, 2, 1, 8, 7, 6, 3, 5, 9] -- How many digits to reverse? 4
[8, 1, 2, 4, 7, 6, 3, 5, 9] -- How many digits to reverse? 8
[5, 3, 6, 7, 4, 2, 1, 8, 9] -- How many digits to reverse? 4
[7, 6, 3, 5, 4, 2, 1, 8, 9] -- How many digits to reverse? 7
[1, 2, 4, 5, 3, 6, 7, 8, 9] -- How many digits to reverse? 4
[5, 4, 2, 1, 3, 6, 7, 8, 9] -- How many digits to reverse? 5
[3, 1, 2, 4, 5, 6, 7, 8, 9] -- How many digits to reverse? 3
[2, 1, 3, 4, 5, 6, 7, 8, 9] -- How many digits to reverse? 2
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Your score: 8

Tcl

<lang tcl>package require Tcl 8.5

  1. Simple shuffler, not very efficient but good enough for here

proc shuffle list {

   set result {}
   while {[llength $list]} {

set i [expr {int([llength $list] * rand())}] lappend result [lindex $list $i] set list [lreplace $list $i $i]

   }
   return $result

}

  1. Returns the list with the prefix of it reversed

proc flipfirst {list n} {

   concat [lreverse [lrange $list 0 $n-1]] [lrange $list $n end]

}

  1. Core game engine; list to play with is optional argument

proc nrgame Template:Target "1 2 3 4 5 6 7 8 9" {

   set nums $target
   while {$nums eq $target} {set nums [shuffle $nums]}
   set goes 0
   while {$nums ne $target} {

incr goes puts -nonewline "#${goes}: List is '[join $nums {, }]', how many to reverse? " flush stdout gets stdin n if {$n eq "q"} {return quit} # Input validation would go here set nums [flipfirst $nums $n]

   }
   return $goes

}

  1. Print some instructions and wait for the user to win

puts "Welcome to the Number Reversal Game!" puts "------------------------------------" puts "I'll show you a list of numbers, you need to reverse prefixes of them" puts "to get the whole list in ascending order. A 'q' will quit early.\n" puts "" set outcome [nrgame] if {$outcome ne "quit"} {

   puts "\nYou took $outcome attempts to put the digits in order."

}</lang> Sample output:

Welcome to the Number Reversal Game!
------------------------------------
I'll show you a list of numbers, you need to reverse prefixes of them
to get the whole list in ascending order. A 'q' will quit early.


#1: List is '8, 6, 2, 5, 7, 9, 3, 1, 4', how many to reverse? 6
#2: List is '9, 7, 5, 2, 6, 8, 3, 1, 4', how many to reverse? 9
#3: List is '4, 1, 3, 8, 6, 2, 5, 7, 9', how many to reverse? 4
#4: List is '8, 3, 1, 4, 6, 2, 5, 7, 9', how many to reverse? 8
#5: List is '7, 5, 2, 6, 4, 1, 3, 8, 9', how many to reverse? 7
#6: List is '3, 1, 4, 6, 2, 5, 7, 8, 9', how many to reverse? 4
#7: List is '6, 4, 1, 3, 2, 5, 7, 8, 9', how many to reverse? 6
#8: List is '5, 2, 3, 1, 4, 6, 7, 8, 9', how many to reverse? 5
#9: List is '4, 1, 3, 2, 5, 6, 7, 8, 9', how many to reverse? 4
#10: List is '2, 3, 1, 4, 5, 6, 7, 8, 9', how many to reverse? 2
#11: List is '3, 2, 1, 4, 5, 6, 7, 8, 9', how many to reverse? 3

You took 11 attempts to put the digits in order.