-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.ts
85 lines (81 loc) · 2.54 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env node
import * as fs from 'fs'
import {promisify} from 'util'
import * as sb from 'structure-bytes'
import {makeBoard, makeCages} from './make-board'
import {makeSolvingBoard} from './solve'
import {Cage, puzzleType, solutionType} from './types'
const SOLUTION_FILE = 'solution.sbv'
const CAGINGS_DIR = 'cagings'
function usageError() {
throw new Error('Usage: ./main.js boardSize')
}
const {argv} = process
if (argv.length !== 3) usageError()
const size = Number(argv[2])
if (isNaN(size)) usageError()
const board = makeBoard(size)
sb.writeValue({
type: solutionType,
value: ([] as number[]).concat(...board),
outStream: fs.createWriteStream(SOLUTION_FILE)
}, err => {
if (err) throw err
console.log('Saved solution')
promisify(fs.mkdir)(CAGINGS_DIR)
.catch(_ =>
promisify(fs.readdir)(CAGINGS_DIR)
.then(difficulties => Promise.all(difficulties.map(difficulty => {
const difficultyDir = CAGINGS_DIR + '/' + difficulty
return promisify(fs.readdir)(difficultyDir)
.then(files => Promise.all(files.map(file =>
promisify(fs.unlink)(difficultyDir + '/' + file)
)))
.then(_ => promisify(fs.rmdir)(difficultyDir))
})))
)
.then(makeCaging)
})
const stepsCount: number[] = [] //map of difficulties to count of cagings; key 0 for unsolvable
function makeCaging() {
let cages: Cage[], steps: number
let solved = false
while (!solved) {
cages = makeCages(board)
const solvingBoard = makeSolvingBoard(size, cages)
steps = solvingBoard.solve()
if (solvingBoard.noPossibilities()) { //should never happen
console.log('Failed solve\n' + solvingBoard.toString())
}
else if (solvingBoard.isSolved()) solved = true
else stepsCount[0] = (stepsCount[0] || 0) + 1
}
stepsCount[steps!] = (stepsCount[steps] || 0) + 1
logPuzzleCounts()
const cagingDir = CAGINGS_DIR + '/' + String(steps)
promisify(fs.mkdir)(cagingDir).catch(_ => {})
.then(() => new Promise<void>((resolve, reject) =>
sb.writeValue({
type: puzzleType,
value: {max: size, cages},
outStream: fs.createWriteStream(cagingDir + '/' + String(stepsCount[steps]) + '.sbv')
}, err => {
if (err) reject(err)
else resolve()
})
))
.then(makeCaging)
}
function logPuzzleCounts() {
const failed = stepsCount[0] || 0
const succeeded = stepsCount.reduce((a, b) => a + b, 0) - failed
console.log(
'Successes:',
(succeeded / (failed + succeeded) * 100).toFixed(2) + '%;',
'Counts:',
stepsCount
.map((count, steps) => String(steps) + ': ' + String(count))
.filter(x => x) //take out all steps with no count
.join(', ')
)
}