smalltalk: eight-queens classic program (sizes 1/4/5 verified)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -82,4 +82,64 @@
|
||||
^ b memoFib: 10")
|
||||
55)
|
||||
|
||||
;; ── eight-queens.st (kept in sync with lib/smalltalk/tests/programs/eight-queens.st) ──
|
||||
(define
|
||||
queens-source
|
||||
"Object subclass: #EightQueens
|
||||
instanceVariableNames: 'columns count size'!
|
||||
|
||||
!EightQueens methodsFor: 'init'!
|
||||
init
|
||||
size := 8.
|
||||
columns := Array new: size.
|
||||
count := 0.
|
||||
^ self!
|
||||
|
||||
size: n
|
||||
size := n.
|
||||
columns := Array new: n.
|
||||
count := 0.
|
||||
^ self! !
|
||||
|
||||
!EightQueens methodsFor: 'access'!
|
||||
count ^ count!
|
||||
|
||||
size ^ size! !
|
||||
|
||||
!EightQueens methodsFor: 'solve'!
|
||||
solve
|
||||
self placeRow: 1.
|
||||
^ count!
|
||||
|
||||
placeRow: row
|
||||
row > size ifTrue: [count := count + 1. ^ self].
|
||||
1 to: size do: [:col |
|
||||
(self isSafe: col atRow: row) ifTrue: [
|
||||
columns at: row put: col.
|
||||
self placeRow: row + 1]]!
|
||||
|
||||
isSafe: col atRow: row
|
||||
| r prevCol delta |
|
||||
r := 1.
|
||||
[r < row] whileTrue: [
|
||||
prevCol := columns at: r.
|
||||
prevCol = col ifTrue: [^ false].
|
||||
delta := col - prevCol.
|
||||
delta abs = (row - r) ifTrue: [^ false].
|
||||
r := r + 1].
|
||||
^ true! !")
|
||||
|
||||
(smalltalk-load queens-source)
|
||||
|
||||
;; Backtracking is correct but slow on the spec interpreter (call/cc per
|
||||
;; method, dict-based ivar reads). 4- and 5-queens cover the corners
|
||||
;; and run in under 10s; 6+ work but would push past the test-runner
|
||||
;; timeout. The class itself defaults to size 8, ready for the JIT.
|
||||
(st-test "1 queen on 1x1 board" (evp "^ (EightQueens new size: 1) solve") 1)
|
||||
(st-test "4 queens on 4x4 board" (evp "^ (EightQueens new size: 4) solve") 2)
|
||||
(st-test "5 queens on 5x5 board" (evp "^ (EightQueens new size: 5) solve") 10)
|
||||
(st-test "EightQueens class is registered" (st-class-exists? "EightQueens") true)
|
||||
(st-test "EightQueens init sets size 8"
|
||||
(evp "^ EightQueens new init size") 8)
|
||||
|
||||
(list st-test-pass st-test-fail)
|
||||
|
||||
47
lib/smalltalk/tests/programs/eight-queens.st
Normal file
47
lib/smalltalk/tests/programs/eight-queens.st
Normal file
@@ -0,0 +1,47 @@
|
||||
"Eight-queens — classic backtracking search. Counts the number of
|
||||
distinct placements of 8 queens on an 8x8 board with no two attacking.
|
||||
Expected count: 92."
|
||||
|
||||
Object subclass: #EightQueens
|
||||
instanceVariableNames: 'columns count size'!
|
||||
|
||||
!EightQueens methodsFor: 'init'!
|
||||
init
|
||||
size := 8.
|
||||
columns := Array new: size.
|
||||
count := 0.
|
||||
^ self!
|
||||
|
||||
size: n
|
||||
size := n.
|
||||
columns := Array new: n.
|
||||
count := 0.
|
||||
^ self! !
|
||||
|
||||
!EightQueens methodsFor: 'access'!
|
||||
count ^ count!
|
||||
|
||||
size ^ size! !
|
||||
|
||||
!EightQueens methodsFor: 'solve'!
|
||||
solve
|
||||
self placeRow: 1.
|
||||
^ count!
|
||||
|
||||
placeRow: row
|
||||
row > size ifTrue: [count := count + 1. ^ self].
|
||||
1 to: size do: [:col |
|
||||
(self isSafe: col atRow: row) ifTrue: [
|
||||
columns at: row put: col.
|
||||
self placeRow: row + 1]]!
|
||||
|
||||
isSafe: col atRow: row
|
||||
| r prevCol delta |
|
||||
r := 1.
|
||||
[r < row] whileTrue: [
|
||||
prevCol := columns at: r.
|
||||
prevCol = col ifTrue: [^ false].
|
||||
delta := col - prevCol.
|
||||
delta abs = (row - r) ifTrue: [^ false].
|
||||
r := r + 1].
|
||||
^ true! !
|
||||
Reference in New Issue
Block a user