Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 //-----------------------------------------------------------------------------
8 var BUGNUMBER = 380237;
9 var summary = 'Generator expressions - sudoku';
10 var actual = '';
11 var expect = '';
14 //-----------------------------------------------------------------------------
15 test();
16 //-----------------------------------------------------------------------------
18 function test()
19 {
20 enterFunc ('test');
21 printBugNumber(BUGNUMBER);
22 printStatus (summary);
24 if (this.version) version(180);
26 // XXX should be standard (and named clone, after Java?)
27 Object.prototype.copy = function () {
28 let o = {}
29 for (let i in this)
30 o[i] = this[i]
31 return o
32 }
34 // Make arrays and strings act more like Python lists by iterating their values, not their keys.
35 Array.prototype.__iterator__ = String.prototype.__iterator__ = function () {
36 for (let i = 0; i < this.length; i++)
37 yield this[i]
38 }
40 // Containment testing for arrays and strings that should be coherent with their __iterator__.
41 Array.prototype.contains = String.prototype.contains = function (e) {
42 return this.indexOf(e) != -1
43 }
45 Array.prototype.repeat = String.prototype.repeat = function (n) {
46 let s = this.constructor()
47 for (let i = 0; i < n; i++)
48 s = s.concat(this)
49 return s
50 }
52 String.prototype.center = function (w) {
53 let n = this.length
54 if (w <= n)
55 return this
56 let m = Math.floor((w - n) / 2)
57 return ' '.repeat(m) + this + ' '.repeat(w - n - m)
58 }
60 Array.prototype.toString = Array.prototype.toSource
61 Object.prototype.toString = Object.prototype.toSource
63 // XXX thought spurred by the next two functions: array extras should default to identity function
65 function all(seq) {
66 for (let e in seq)
67 if (!e)
68 return false
69 return true
70 }
72 function some(seq) {
73 for (let e in seq)
74 if (e)
75 return e
76 return false
77 }
79 function cross(A, B) {
80 return [a+b for (a in A) for (b in B)]
81 }
83 function dict(A) {
84 let d = {}
85 for (let e in A)
86 d[e[0]] = e[1]
87 return d
88 }
90 function set(A) {
91 let s = []
92 for (let e in A)
93 if (!s.contains(e))
94 s.push(e)
95 return s
96 }
98 function zip(A, B) {
99 let z = []
100 let n = Math.min(A.length, B.length)
101 for (let i = 0; i < n; i++)
102 z.push([A[i], B[i]])
103 return z
104 }
106 rows = 'ABCDEFGHI'
107 cols = '123456789'
108 digits = '123456789'
109 squares = cross(rows, cols)
110 unitlist = [cross(rows, c) for (c in cols)]
111 .concat([cross(r, cols) for (r in rows)])
112 .concat([cross(rs, cs) for (rs in ['ABC','DEF','GHI']) for (cs in ['123','456','789'])])
113 units = dict([s, [u for (u in unitlist) if (u.contains(s))]]
114 for (s in squares))
115 peers = dict([s, set([s2 for (u in units[s]) for (s2 in u) if (s2 != s)])]
116 for (s in squares))
118 // Given a string of 81 digits (or . or 0 or -), return a dict of {cell:values}.
119 function parse_grid(grid) {
120 grid = [c for (c in grid) if ('0.-123456789'.contains(c))]
121 let values = dict([s, digits] for (s in squares))
123 for (let [s, d] in zip(squares, grid))
124 if (digits.contains(d) && !assign(values, s, d))
125 return false
126 return values
127 }
129 // Eliminate all the other values (except d) from values[s] and propagate.
130 function assign(values, s, d) {
131 if (all(eliminate(values, s, d2) for (d2 in values[s]) if (d2 != d)))
132 return values
133 return false
134 }
136 // Eliminate d from values[s]; propagate when values or places <= 2.
137 function eliminate(values, s, d) {
138 if (!values[s].contains(d))
139 return values // Already eliminated
140 values[s] = values[s].replace(d, '')
141 if (values[s].length == 0)
142 return false // Contradiction: removed last value
143 if (values[s].length == 1) {
144 // If there is only one value (d2) left in square, remove it from peers
145 let d2 = values[s][0]
146 if (!all(eliminate(values, s2, d2) for (s2 in peers[s])))
147 return false
148 }
149 // Now check the places where d appears in the units of s
150 for (let u in units[s]) {
151 let dplaces = [s for (s in u) if (values[s].contains(d))]
152 if (dplaces.length == 0)
153 return false
154 if (dplaces.length == 1)
155 // d can only be in one place in unit; assign it there
156 if (!assign(values, dplaces[0], d))
157 return false
158 }
159 return values
160 }
162 // Used for debugging.
163 function print_board(values) {
164 let width = 1 + Math.max.apply(Math, [values[s].length for (s in squares)])
165 let line = '\n' + ['-'.repeat(width*3)].repeat(3).join('+')
166 for (let r in rows)
167 print([values[r+c].center(width) + ('36'.contains(c) && '|' || '')
168 for (c in cols)].join('') + ('CF'.contains(r) && line || ''))
169 print('\n')
170 }
172 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.."
174 print_board(parse_grid(easy))
176 // Using depth-first search and constraint propagation, try all possible values.
177 function search(values) {
178 if (!values)
179 return false // Failed earlier
180 if (all(values[s].length == 1 for (s in squares)))
181 return values // Solved!
183 // Choose the unfilled square s with the fewest possibilities
184 // XXX Math.min etc. should work with generator expressions and other iterators
185 // XXX Math.min etc. should work on arrays (lists or tuples in Python) as well as numbers
186 let a = [values[s].length + s for (s in squares) if (values[s].length > 1)].sort()
187 let s = a[0].slice(-2)
189 return some(search(assign(values.copy(), s, d)) for (d in values[s]))
190 }
192 hard = '4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......'
194 print_board(search(parse_grid(hard)))
196 delete Object.prototype.copy;
198 reportCompare(expect, actual, summary);
200 exitFunc ('test');
201 }