Flipping bits game: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Grammar)
(→‎{{header|Perl 6}}: add a Perl 6 entry)
Line 17: Line 17:
# The number of moves taken so far should be shown.
# The number of moves taken so far should be shown.
Show an example of a short game here, on this page, for a 3 by 3 array of bits.
Show an example of a short game here, on this page, for a 3 by 3 array of bits.

=={{header|Perl 6}}==
Pass in a parameter to set the square size for the puzzle. (Defaults to 4.) Arbitrarily limited to between 1 and 26. Yes, you can choose to solve a 1 element square puzzle, but it won't be very challenging. Accepts upper or lower case letters for columns. Disregards any out-of-range indices. Enter a blank or 0 (zero) to exit.

<lang perl6>sub MAIN ($square = 4) {
say "{$square}? Seriously?" and exit if $square < 1 or $square > 26;
my %bits = map { $_ => %( map { $_ => 0 }, ('A' .. *)[^ $square] ) },
(1 .. *)[^ $square];
scramble %bits;
my $target = build %bits;
scramble %bits until build(%bits) ne $target;
display($target, %bits);
my $turns = 0;
while my $flip = prompt "Turn {++$turns}: Flip which row / column? " {
flip $flip.match(/\w/).uc, %bits;
if display($target, %bits) {
say "Hurray! You solved it in $turns turns.";
last;
}
}
}

sub display($goal, %hash) {
shell('clear');
say "Goal\n$goal\nYou";
my $this = build %hash;
say $this;
return ($goal eq $this);
}

sub flip ($a, %hash) {
given $a {
when any(keys %hash) {
%hash{$a}{$_} = %hash{$a}{$_} +^ 1 for %hash{$a}.keys
};
when any(keys %hash{'1'}) {
%hash{$_}{$a} = %hash{$_}{$a} +^ 1 for %hash.keys
};
}
}

sub build (%hash) {
my $string = ' ';
$string ~= sprintf "%2s ", $_ for keys %hash{'1'};
$string ~= "\n";
for keys %hash -> $key {
$string ~= sprintf "%2s ", $key;
$string ~= sprintf "%2s ", $_ for values %hash{$key};
$string ~= "\n";
};
$string
}

sub scramble(%hash) {
my @keys = keys %hash;
@keys ,= keys %hash{'1'};
flip $_, %hash for @keys.pick( @keys/2 );
}</lang>
A sample 3 x 3 game might look like this:
<pre>Goal
A B C
1 1 1 0
2 0 0 1
3 1 1 0

You
A B C
1 0 0 0
2 1 1 1
3 1 1 1

Turn 1: Flip which row / column? 2

Goal
A B C
1 1 1 0
2 0 0 1
3 1 1 0

You
A B C
1 0 0 0
2 0 0 0
3 1 1 1

Turn 2: Flip which row / column? 1

Goal
A B C
1 1 1 0
2 0 0 1
3 1 1 0

You
A B C
1 1 1 1
2 0 0 0
3 1 1 1

Turn 3: Flip which row / column? c

Goal
A B C
1 1 1 0
2 0 0 1
3 1 1 0

You
A B C
1 1 1 0
2 0 0 1
3 1 1 0

Hurray! You solved it in 3 turns.</pre>



=={{header|Python}}==
=={{header|Python}}==

Revision as of 01:37, 11 July 2013

Flipping bits game is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
The game

Given an N by N sqare array of zeroes or ones in an initial configuration, and a target configuration of zeroes and ones The task is to transform one to the other in as few moves as possible by inverting whole numbered rows or whole lettered columns at once, as one move.

In an inversion any 1 becomes 0, and any 0 becomes 1 for that whole row or column.

The Task

The task is to create a program to score for the Flipping bits game.

  1. The game should create an original random target configuration and a starting configuration.
  2. Ensure that the starting position is never the target position.
  3. The target position must be guaranteed as reachable from the starting position.
  4. The number of moves taken so far should be shown.

Show an example of a short game here, on this page, for a 3 by 3 array of bits.

Perl 6

Pass in a parameter to set the square size for the puzzle. (Defaults to 4.) Arbitrarily limited to between 1 and 26. Yes, you can choose to solve a 1 element square puzzle, but it won't be very challenging. Accepts upper or lower case letters for columns. Disregards any out-of-range indices. Enter a blank or 0 (zero) to exit.

<lang perl6>sub MAIN ($square = 4) {

   say "{$square}? Seriously?" and exit if $square < 1 or $square > 26;
   my %bits = map { $_ => %( map { $_ => 0 }, ('A' .. *)[^ $square] ) },
       (1 .. *)[^ $square];
   scramble %bits;
   my $target = build %bits;
   scramble %bits until build(%bits) ne $target;
   display($target, %bits);
   my $turns = 0;
   while my $flip = prompt "Turn {++$turns}: Flip which row / column? " {
       flip $flip.match(/\w/).uc, %bits;
       if display($target, %bits) {
           say "Hurray! You solved it in $turns turns.";
           last;
       }
   }

}

sub display($goal, %hash) {

   shell('clear');
   say "Goal\n$goal\nYou";
   my $this = build %hash;
   say $this;
   return ($goal eq $this);

}

sub flip ($a, %hash) {

   given $a {
       when any(keys %hash) {
           %hash{$a}{$_} = %hash{$a}{$_} +^ 1 for %hash{$a}.keys
       };
       when any(keys %hash{'1'}) {
           %hash{$_}{$a} = %hash{$_}{$a} +^ 1 for %hash.keys
       };
   }

}

sub build (%hash) {

   my $string = '   ';
   $string ~= sprintf "%2s ", $_ for keys %hash{'1'};
   $string ~= "\n";
   for keys %hash -> $key {
       $string ~= sprintf "%2s ", $key;
       $string ~= sprintf "%2s ", $_  for values %hash{$key};
       $string ~=  "\n";
   };
   $string

}

sub scramble(%hash) {

   my @keys = keys %hash;
   @keys ,= keys %hash{'1'};
   flip $_,  %hash for @keys.pick( @keys/2 );

}</lang> A sample 3 x 3 game might look like this:

Goal
    A  B  C 
 1  1  1  0 
 2  0  0  1 
 3  1  1  0 

You
    A  B  C 
 1  0  0  0 
 2  1  1  1 
 3  1  1  1 

Turn 1: Flip which row / column? 2

Goal
    A  B  C 
 1  1  1  0 
 2  0  0  1 
 3  1  1  0 

You
    A  B  C 
 1  0  0  0 
 2  0  0  0 
 3  1  1  1 

Turn 2: Flip which row / column? 1

Goal
    A  B  C 
 1  1  1  0 
 2  0  0  1 
 3  1  1  0 

You
    A  B  C 
 1  1  1  1 
 2  0  0  0 
 3  1  1  1 

Turn 3: Flip which row / column? c

Goal
    A  B  C 
 1  1  1  0 
 2  0  0  1 
 3  1  1  0 

You
    A  B  C 
 1  1  1  0 
 2  0  0  1 
 3  1  1  0 

Hurray! You solved it in 3 turns.


Python

<lang python>""" Given a %i by %i sqare array of zeroes or ones in an initial configuration, and a target configuration of zeroes and ones The task is to transform one to the other in as few moves as possible by inverting whole numbered rows or whole lettered columns at once. In an inversion any 1 becomes 0 and any 0 becomes 1 for that whole row or column.

"""

from random import randrange from copy import deepcopy from string import ascii_lowercase


try: # 2to3 fix

   input = raw_input

except:

   pass

N = 3 # N x N Square arrray

board = [[0]* N for i in range(N)]

def setbits(board, count=1):

   for i in range(count):
       board[randrange(N)][randrange(N)] ^= 1

def shuffle(board, count=1):

   for i in range(count):
       if randrange(0, 2):
           fliprow(randrange(N))
       else:
           flipcol(randrange(N))


def pr(board, comment=):

   print(str(comment))
   print('     ' + ' '.join(ascii_lowercase[i] for i in range(N)))
   print('  ' + '\n  '.join(' '.join(['%2s' % j] + [str(i) for i in line])
                            for j, line in enumerate(board, 1)))

def init(board):

   setbits(board, count=randrange(N)+1)
   target = deepcopy(board)
   while board == target:
       shuffle(board, count=2 * N)
   prompt = '  X, T, or 1-%i / %s-%s to flip: ' % (N, ascii_lowercase[0], 
                                                   ascii_lowercase[N-1])
   return target, prompt

def fliprow(i):

   board[i-1][:] = [x ^ 1 for x in board[i-1] ]
   

def flipcol(i):

   for row in board:
       row[i] ^= 1

if __name__ == '__main__':

   print(__doc__ % (N, N))
   target, prompt = init(board)
   pr(target, 'Target configuration is:')
   print()
   turns = 0
   while board != target:
       turns += 1
       pr(board, '%i:' % turns)
       ans = input(prompt).strip()
       if (len(ans) == 1 
           and ans in ascii_lowercase and ascii_lowercase.index(ans) < N):
           flipcol(ascii_lowercase.index(ans))
       elif ans and all(ch in '0123456789' for ch in ans) and 1 <= int(ans) <= N:
           fliprow(int(ans))
       elif ans == 'T':
           pr(target, 'Target configuration is:')
           turns -= 1
       elif ans == 'X':
           break
       else:
           print("  I don't understand %r... Try again. "
                 "(X to exit or T to show target)\n" % ans[:9])
           turns -= 1
   else:
       print('\nWell done!\nBye.')</lang>
Output:
Given a 3 by 3 sqare array of zeroes or ones in an initial
configuration, and a target configuration of zeroes and ones
The task is to transform one to the other in as few moves as 
possible by inverting whole numbered rows or whole lettered 
columns at once.
In an inversion any 1 becomes 0 and any 0 becomes 1 for that
whole row or column.


Target configuration is:
     a b c
   1 0 1 0
   2 0 0 0
   3 0 0 0

1:
     a b c
   1 1 0 0
   2 0 0 1
   3 0 0 1
  X, T, or 1-3 / a-c to flip: 1
2:
     a b c
   1 0 1 1
   2 0 0 1
   3 0 0 1
  X, T, or 1-3 / a-c to flip: c

Well done!
Bye.
Showing bad/other inputs
Target configuration is:
     a b c
   1 0 0 0
   2 0 0 0
   3 0 0 1

1:
     a b c
   1 1 0 1
   2 0 1 0
   3 0 1 1
  X, T, or 1-3 / a-c to flip: 3
2:
     a b c
   1 1 0 1
   2 0 1 0
   3 1 0 0
  X, T, or 1-3 / a-c to flip: 4
  I don't understand '4'... Try again. (X to exit or T to show target)

2:
     a b c
   1 1 0 1
   2 0 1 0
   3 1 0 0
  X, T, or 1-3 / a-c to flip: c
3:
     a b c
   1 1 0 0
   2 0 1 1
   3 1 0 1
  X, T, or 1-3 / a-c to flip: d
  I don't understand 'd'... Try again. (X to exit or T to show target)

3:
     a b c
   1 1 0 0
   2 0 1 1
   3 1 0 1
  X, T, or 1-3 / a-c to flip: T
Target configuration is:
     a b c
   1 0 0 0
   2 0 0 0
   3 0 0 1
3:
     a b c
   1 1 0 0
   2 0 1 1
   3 1 0 1
  X, T, or 1-3 / a-c to flip: X