js/src/tests/js1_8/genexps/regress-380237-01.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/tests/js1_8/genexps/regress-380237-01.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,201 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +
    1.10 +//-----------------------------------------------------------------------------
    1.11 +var BUGNUMBER = 380237;
    1.12 +var summary = 'Generator expressions - sudoku';
    1.13 +var actual = '';
    1.14 +var expect = '';
    1.15 +
    1.16 +
    1.17 +//-----------------------------------------------------------------------------
    1.18 +test();
    1.19 +//-----------------------------------------------------------------------------
    1.20 +
    1.21 +function test()
    1.22 +{
    1.23 +  enterFunc ('test');
    1.24 +  printBugNumber(BUGNUMBER);
    1.25 +  printStatus (summary);
    1.26 +
    1.27 +if (this.version) version(180);
    1.28 +
    1.29 +// XXX should be standard (and named clone, after Java?)
    1.30 +Object.prototype.copy = function () {
    1.31 +    let o = {}
    1.32 +    for (let i in this)
    1.33 +        o[i] = this[i]
    1.34 +    return o
    1.35 +}
    1.36 +
    1.37 +// Make arrays and strings act more like Python lists by iterating their values, not their keys.
    1.38 +Array.prototype.__iterator__ = String.prototype.__iterator__ = function () {
    1.39 +    for (let i = 0; i < this.length; i++)
    1.40 +        yield this[i]
    1.41 +}
    1.42 +
    1.43 +// Containment testing for arrays and strings that should be coherent with their __iterator__.
    1.44 +Array.prototype.contains = String.prototype.contains = function (e) {
    1.45 +    return this.indexOf(e) != -1
    1.46 +}
    1.47 +
    1.48 +Array.prototype.repeat = String.prototype.repeat = function (n) {
    1.49 +    let s = this.constructor()
    1.50 +    for (let i = 0; i < n; i++)
    1.51 +        s = s.concat(this)
    1.52 +    return s
    1.53 +}
    1.54 +
    1.55 +String.prototype.center = function (w) {
    1.56 +    let n = this.length
    1.57 +    if (w <= n)
    1.58 +        return this
    1.59 +    let m = Math.floor((w - n) / 2)
    1.60 +    return ' '.repeat(m) + this + ' '.repeat(w - n - m)
    1.61 +}
    1.62 +
    1.63 +Array.prototype.toString = Array.prototype.toSource
    1.64 +Object.prototype.toString = Object.prototype.toSource
    1.65 +
    1.66 +// XXX thought spurred by the next two functions: array extras should default to identity function
    1.67 +
    1.68 +function all(seq) {
    1.69 +    for (let e in seq)
    1.70 +        if (!e)
    1.71 +            return false
    1.72 +    return true
    1.73 +}
    1.74 +
    1.75 +function some(seq) {
    1.76 +    for (let e in seq)
    1.77 +        if (e)
    1.78 +            return e
    1.79 +    return false
    1.80 +}
    1.81 +
    1.82 +function cross(A, B) {
    1.83 +    return [a+b for (a in A) for (b in B)]
    1.84 +}
    1.85 +
    1.86 +function dict(A) {
    1.87 +    let d = {}
    1.88 +    for (let e in A)
    1.89 +        d[e[0]] = e[1]
    1.90 +    return d
    1.91 +}
    1.92 +
    1.93 +function set(A) {
    1.94 +    let s = []
    1.95 +    for (let e in A)
    1.96 +        if (!s.contains(e))
    1.97 +            s.push(e)
    1.98 +    return s
    1.99 +}
   1.100 +
   1.101 +function zip(A, B) {
   1.102 +    let z = []
   1.103 +    let n = Math.min(A.length, B.length)
   1.104 +    for (let i = 0; i < n; i++)
   1.105 +        z.push([A[i], B[i]])
   1.106 +    return z
   1.107 +}
   1.108 +
   1.109 +rows = 'ABCDEFGHI'
   1.110 +cols = '123456789'
   1.111 +digits   = '123456789'
   1.112 +squares  = cross(rows, cols)
   1.113 +unitlist = [cross(rows, c) for (c in cols)]
   1.114 +           .concat([cross(r, cols) for (r in rows)])
   1.115 +           .concat([cross(rs, cs) for (rs in ['ABC','DEF','GHI']) for (cs in ['123','456','789'])])
   1.116 +units = dict([s, [u for (u in unitlist) if (u.contains(s))]] 
   1.117 +             for (s in squares))
   1.118 +peers = dict([s, set([s2 for (u in units[s]) for (s2 in u) if (s2 != s)])]
   1.119 +             for (s in squares))
   1.120 +
   1.121 +// Given a string of 81 digits (or . or 0 or -), return a dict of {cell:values}.
   1.122 +function parse_grid(grid) {
   1.123 +    grid = [c for (c in grid) if ('0.-123456789'.contains(c))]
   1.124 +    let values = dict([s, digits] for (s in squares))
   1.125 +
   1.126 +    for (let [s, d] in zip(squares, grid))
   1.127 +        if (digits.contains(d) && !assign(values, s, d))
   1.128 +            return false
   1.129 +    return values
   1.130 +}
   1.131 +
   1.132 +// Eliminate all the other values (except d) from values[s] and propagate.
   1.133 +function assign(values, s, d) {
   1.134 +    if (all(eliminate(values, s, d2) for (d2 in values[s]) if (d2 != d)))
   1.135 +        return values
   1.136 +    return false
   1.137 +}
   1.138 +
   1.139 +// Eliminate d from values[s]; propagate when values or places <= 2.
   1.140 +function eliminate(values, s, d) {
   1.141 +    if (!values[s].contains(d))
   1.142 +        return values // Already eliminated
   1.143 +    values[s] = values[s].replace(d, '')
   1.144 +    if (values[s].length == 0)
   1.145 +	return false  // Contradiction: removed last value
   1.146 +    if (values[s].length == 1) {
   1.147 +	// If there is only one value (d2) left in square, remove it from peers
   1.148 +        let d2 = values[s][0]
   1.149 +        if (!all(eliminate(values, s2, d2) for (s2 in peers[s])))
   1.150 +            return false
   1.151 +    }
   1.152 +    // Now check the places where d appears in the units of s
   1.153 +    for (let u in units[s]) {
   1.154 +	let dplaces = [s for (s in u) if (values[s].contains(d))]
   1.155 +	if (dplaces.length == 0)
   1.156 +	    return false
   1.157 +	if (dplaces.length == 1)
   1.158 +	    // d can only be in one place in unit; assign it there
   1.159 +            if (!assign(values, dplaces[0], d))
   1.160 +                return false
   1.161 +    }
   1.162 +    return values
   1.163 +}
   1.164 +
   1.165 +// Used for debugging.
   1.166 +function print_board(values) {
   1.167 +    let width = 1 + Math.max.apply(Math, [values[s].length for (s in squares)])
   1.168 +    let line = '\n' + ['-'.repeat(width*3)].repeat(3).join('+')
   1.169 +    for (let r in rows)
   1.170 +        print([values[r+c].center(width) + ('36'.contains(c) && '|' || '')
   1.171 +               for (c in cols)].join('') + ('CF'.contains(r) && line || ''))
   1.172 +    print('\n')
   1.173 +}
   1.174 +
   1.175 +easy = "..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3.."
   1.176 +
   1.177 +print_board(parse_grid(easy))
   1.178 +
   1.179 +// Using depth-first search and constraint propagation, try all possible values.
   1.180 +function search(values) {
   1.181 +    if (!values)
   1.182 +        return false    // Failed earlier
   1.183 +    if (all(values[s].length == 1 for (s in squares))) 
   1.184 +        return values   // Solved!
   1.185 +
   1.186 +    // Choose the unfilled square s with the fewest possibilities
   1.187 +    // XXX Math.min etc. should work with generator expressions and other iterators
   1.188 +    // XXX Math.min etc. should work on arrays (lists or tuples in Python) as well as numbers
   1.189 +    let a = [values[s].length + s for (s in squares) if (values[s].length > 1)].sort()
   1.190 +    let s = a[0].slice(-2)
   1.191 +
   1.192 +    return some(search(assign(values.copy(), s, d)) for (d in values[s]))
   1.193 +}
   1.194 +
   1.195 +hard = '4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......'
   1.196 +
   1.197 +print_board(search(parse_grid(hard)))
   1.198 +
   1.199 +  delete Object.prototype.copy;
   1.200 + 
   1.201 +  reportCompare(expect, actual, summary);
   1.202 +
   1.203 +  exitFunc ('test');
   1.204 +}

mercurial