Twelve statements: Difference between revisions

Content added Content deleted
(→‎{{header|Python}}: Add implementation.)
(Go solution)
Line 21: Line 21:


Extra credit: also print out a table of near misses, that is, solutions that are contradicted by only a single statement.
Extra credit: also print out a table of near misses, that is, solutions that are contradicted by only a single statement.
=={{header|Go}}==
<lang go>package main

import "fmt"

// its' not too much more work to check all the permutations concurrently
var solution = make(chan int)
var nearMiss = make(chan int)
var done = make(chan bool)

func main() {
// iterate and use the bits as the permutation
for i := 0; i < 4096; i++ {
go checkPerm(i)
}
// collect the misses and list them after the complete solution(s)
var ms []int
for i := 0; i < 4096; {
select {
case <-done:
i++
case s := <-solution:
print12("solution", s)
case m := <-nearMiss:
ms = append(ms, m)
}
}
for _, m := range ms {
print12("near miss", m)
}
}

func print12(label string, bits int) {
fmt.Print(label, ":")
for i := 1; i <= 12; i++ {
if bits&1 == 1 {
fmt.Print(" ", i)
}
bits >>= 1
}
fmt.Println()
}

func checkPerm(tz int) {
// closure returns true if tz bit corresponding to
// 1-based statement number is 1.
ts := func(n uint) bool {
return tz>>(n-1)&1 == 1
}
// variadic closure returns number of statements listed as arguments
// which have corresponding tz bit == 1.
ntrue := func(xs ...uint) int {
nt := 0
for _, x := range xs {
if ts(x) {
nt++
}
}
return nt
}
// a flag used on repeated calls to test.
// set to true when first contradiction is found.
// if another is found, this function (checkPerm) can "short circuit"
// and return immediately without checking additional statements.
var con bool
// closure called to test each statement
test := func(statement uint, b bool) {
switch {
case ts(statement) == b:
case con:
panic("bail")
default:
con = true
}
}
// short circuit mechanism
defer func() {
if x := recover(); x != nil {
if msg, ok := x.(string); !ok && msg != "bail" {
panic(x)
}
}
done <- true
}()

// 1. This is a numbered list of twelve statements.
test(1, true)

// 2. Exactly 3 of the last 6 statements are true.
test(2, ntrue(7, 8, 9, 10, 11, 12) == 3)

// 3. Exactly 2 of the even-numbered statements are true.
test(3, ntrue(2, 4, 6, 8, 10, 12) == 2)

// 4. If statement 5 is true, then statements 6 and 7 are both true.
test(4, !ts(5) || ts(6) && ts(7))

// 5. The 3 preceding statements are all false.
test(5, !ts(4) && !ts(3) && !ts(2))

// 6. Exactly 4 of the odd-numbered statements are true.
test(6, ntrue(1, 3, 5, 7, 9, 11) == 4)

// 7. Either statement 2 or 3 is true, but not both.
test(7, ts(2) != ts(3))

// 8. If statement 7 is true, then 5 and 6 are both true.
test(8, !ts(7) || ts(5) && ts(6))

// 9. Exactly 3 of the first 6 statements are true.
test(9, ntrue(1, 2, 3, 4, 5, 6) == 3)
// 10. The next two statements are both true.
test(10, ts(11) && ts(12))
// 11. Exactly 1 of statements 7, 8 and 9 are true.
test(11, ntrue(7, 8, 9) == 1)
// 12. Exactly 4 of the preceding statements are true.
test(12, ntrue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) == 4)

// no short circuit? send permutation as either near miss or solution
if con {
nearMiss <- tz
} else {
solution <- tz
}
}</lang>
{{out}}
<pre>
solution: 1 3 4 6 7 11
near miss: 1 4
near miss: 1 5
near miss: 1 5 8
near miss: 1 3 4 6 7 9
near miss: 1 3 4 8 9
near miss: 1 4 6 8 9
near miss: 1 2 4 7 8 9
near miss: 1 2 4 7 9 10
near miss: 5 8 11
near miss: 1 5 8 11
near miss: 1 5 6 9 11
near miss: 1 2 4 7 9 12
near miss: 1 4 8 10 11 12
near miss: 4 8 10 11 12
near miss: 5 8 10 11 12
near miss: 1 5 8 10 11 12
</pre>

=={{header|Haskell}}==
=={{header|Haskell}}==
Shows answers with 1 for true, followed by list of indices of incorrect elements each set of 1/0s (index is 0-based).
Shows answers with 1 for true, followed by list of indices of incorrect elements each set of 1/0s (index is 0-based).