All pastes #270438 Raw Edit

Sudoku.fs

public text v1 · immutable
·published 2006-12-07 11:01 UTC
rendered paste body
#! /usr/bin/env gforth



( ============================================================================ )
( = Sudoku input															 = )
( ============================================================================ )

0 constant _

defer |

: <+---------+---------+---------+> ;
: [+---------+---------+---------+] ;

:  |> ( char1 char2 char3 -- )
	rot c, swap c, c, ;

:  |] ( char1 char2 char3 -- )
	>r >r over c! 1+ r> over c! 1+ r> over c! 1+ ;

: <|  ( -- )
	['] |> is | ;

: [|  ( -- )
	['] |] is | ;



( ============================================================================ )
( = Create sudoku															 = )
( ============================================================================ )

create board
	<+---------+---------+---------+>
	<| 2  _  _ | 6	7  _ | _  _  _ |>
	<| _  _  6 | _	_  _ | 2  _  1 |>
	<| 4  _  _ | _	_  _ | 8  _  _ |>
	<+---------+---------+---------+>
	<| 5  _  _ | _	_  9 | 3  _  _ |>
	<| _  3  _ | _	_  _ | _  5  _ |>
	<| _  _  2 | 8	_  _ | _  _  7 |>
	<+---------+---------+---------+>
	<| _  _  1 | _	_  _ | _  _  4 |>
	<| 7  _  8 | _	_  _ | 6  _  _ |>
	<| _  _  _ | _	5  3 | _  _  8 |>
	<+---------+---------+---------+>



( ============================================================================ )
( = Show sudoku																 = )
( ============================================================================ )

: digit>char ( digit -- char )
	[char] 0 + ;

char | constant v-bar
: .v-bar ( -- )
	v-bar emit ;

s" +---------+---------+---------+" 2constant h-bar
: .h-bar ( -- )
	h-bar type cr ;

: .digit>0 ( char -- )
	dup 9 u> IF
		drop [char] ? emit
	ELSE
		digit>char emit
	THEN space ;

: .digit ( char -- )
	dup 0= IF
		drop space space
	ELSE
		.digit>0
	THEN ;

: .1/3row ( addr -- )
	3 0 DO
		space dup c@ .digit
		1+
	LOOP drop .v-bar ;
	
: .row ( addr -- )
	.v-bar 3 0 DO
		dup .1/3row
		3 +
	LOOP drop ;

: .3rows ( addr -- )
	3 0 DO
		dup .row cr
		9 +
	LOOP drop ;

: .board ( addr -- )
	.h-bar 3 0 DO
		dup .3rows .h-bar
		27 +
	LOOP drop ;



( ============================================================================ )
( = Now solve it.															 = )
( ============================================================================ )

: >row    ( index -- row-index )
	9 / 9 * ;

: >column ( index -- column-index )
	9 mod ;

: >box    ( index -- box-index )
	27 /mod 27 * swap 9 mod 3 / 3 * + ;

: row?    ( board+index digit -- found? )
	swap 9 0 DO
		2dup i + c@ = IF
			2drop true
			UNLOOP EXIT
		THEN
	LOOP 2drop false ;

: column? ( board+index digit -- found? )
	swap 9 0 DO
		2dup 9 i * + c@ = IF
			2drop true
			UNLOOP EXIT
		THEN
	LOOP 2drop false ;

: box?    ( board+index digit -- found? )
	swap 03 00 DO 2dup i + c@ = IF 2drop true UNLOOP EXIT THEN LOOP
	     12 09 DO 2dup i + c@ = IF 2drop true UNLOOP EXIT THEN LOOP
	     21 18 DO 2dup i + c@ = IF 2drop true UNLOOP EXIT THEN LOOP
	2drop false ;

: fits? ( board index digit -- unused? )
	>r 2dup >row    + r@ row?    IF 2drop rdrop false ELSE
	   2dup >column + r@ column? IF 2drop rdrop false ELSE
	        >box    + r> box?    IF             false ELSE
	true THEN THEN THEN ;

: guess ( board index -- solved? )
	dup 81 = IF
		2drop true EXIT
	THEN
	
	2dup + c@ IF
		1+ RECURSE EXIT
	THEN
	
	10 1 DO
		2dup i fits? IF
			2dup + i swap c!
			2dup 1+ RECURSE IF
				2drop true
				UNLOOP EXIT
			THEN
		THEN
	LOOP
	+ 0 swap c!
	false ;

: solve		( board -- )
	." Unsolved:" cr
	board .board cr cr
	0 guess IF
		." Solved:" cr
		board .board
	ELSE
		." No solution found."
	THEN cr ;

board solve