The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/pugs

=head1 NAME

nondet_sudoku.p6 - A non deterministic sudoku solver

=head1 DESCRIPTION

A non-working perl 6 implementation of a non deterministic sudoku solver.  

Once we have full continuations, I'll revisit this and add a proper UI, right
now it's simply a demonstration of possibility.

=head1 AUTHOR

Piers Cawley E<lt>pdcawley@bofh.org.ukE<gt>

=head1 COPYRIGHT

Copyright (c) 2005. Piers Cawley. All rights reserved.

This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

See http://www.perl.com/perl/misc/Artistic.html

=cut

use v6;

sub callcc (Code &block) { &block(&?CALLER_CONTINUATION) }

my &give_up = sub { die "Program failed" };

sub choose (*@all_choices) {
  my &old_give_up = &give_up;
  callcc -> $cnt {
    my $try = -> @choices {
      if ! @choices {
        &give_up = &old_give_up;
        give_up;
      }
      else {
        my($choice, @newchoices) = *@choices;
        &give_up = sub { $cnt($try(@newchoices)) };
        $choice;
      }
    };
    $try(@all_choices);
  };
}

sub newchoose (*@all_choices) {
  my &old_give_up = &give_up;
  {
    my $try = -> @choices {
      if ! @choices { &give_up = &old_give_up; give_up }
      else {
        my ($choice, @newchoices) = *@choices;
        &give_up = -> { return $try(@newchoices) };
        $choice;
      }
    };
    $try(@all_choices);
  };
}

# Solve a 4x4 sudoku

my @grid = ( [ choose(1..4), choose(1..4), 2, choose(1..4) ],
             [ 1, choose(1..4), choose(1..4), choose(1..4) ],
             [ choose(1..4), choose(1..4), choose(1..4), 3 ],
             [ choose(1..4), 4, choose(1..4), choose(1..4) ] );

# Row assertions
give_up unless @grid[0].uniq == 4;
give_up unless @grid[1].uniq == 4;
give_up unless @grid[2].uniq == 4;
give_up unless @grid[3].uniq == 4;

# Column assertions
give_up unless [map -> $a {$a[0]}, @grid[0..3]].uniq == 4;
give_up unless [map -> $a {$a[1]}, @grid[0..3]].uniq == 4;
give_up unless [map -> $a {$a[2]}, @grid[0..3]].uniq == 4;
give_up unless [map -> $a {$a[3]}, @grid[0..3]].uniq == 4;

# Subgrid assertions
give_up unless [@grid[0][0], @grid[0][1], @grid[1][0], @grid[1][1]].uniq == 4;
give_up unless [@grid[0][2], @grid[0][3], @grid[1][2], @grid[1][3]].uniq == 4;
give_up unless [@grid[2][0], @grid[2][1], @grid[3][0], @grid[3][1]].uniq == 4;
give_up unless [@grid[2][2], @grid[2][3], @grid[3][2], @grid[3][3]].uniq == 4;

for @grid -> @row { say @row };