Twelve statements: Difference between revisions
Go solution |
de-draft |
||
Line 1:
{{
This puzzle is borrowed from [http://math-frolic.blogspot.co.uk/2012/08/mind-wrenching.html here].
|
Revision as of 02:11, 21 September 2012
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
This puzzle is borrowed from here.
Given the following twelve statements, which of them are true?
1. This is a numbered list of twelve statements. 2. Exactly 3 of the last 6 statements are true. 3. Exactly 2 of the even-numbered statements are true. 4. If statement 5 is true, then statements 6 and 7 are both true. 5. The 3 preceding statements are all false. 6. Exactly 4 of the odd-numbered statements are true. 7. Either statement 2 or 3 is true, but not both. 8. If statement 7 is true, then 5 and 6 are both true. 9. Exactly 3 of the first 6 statements are true. 10. The next two statements are both true. 11. Exactly 1 of statements 7, 8 and 9 are true. 12. Exactly 4 of the preceding statements are true.
When you get tired of trying to figure it out in your head, write a program to solve it, and print the correct answer or answers.
Extra credit: also print out a table of near misses, that is, solutions that are contradicted by only a single statement.
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>
- Output:
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
Haskell
Shows answers with 1 for true, followed by list of indices of incorrect elements each set of 1/0s (index is 0-based).
<lang haskell>import Data.List (findIndices)
tf = mapM (\_ -> [1,0])
wrongness b = findIndices id . zipWith (/=) b . map (fromEnum . ($ b))
statements = [ (==12) . length, 3 ⊂ [length statements-6..], 2 ⊂ [1,3..], 4 → [4..6], 0 ⊂ [1..3], 4 ⊂ [0,2..], 1 ⊂ [1,2], 6 → [4..6], 3 ⊂ [0..5], 2 ⊂ [10,11], 1 ⊂ [6,7,8], 4 ⊂ [0..10] ] where (s ⊂ x) b = s == (sum . map (b!!) . takeWhile (< length b)) x (a → x) b = (b!!a == 0) || all ((==1).(b!!)) x
testall s n = [(b, w) | b <- tf s, w <- [wrongness b s], length w == n]
main = let t = testall statements in do putStrLn "Answer" mapM_ print $ t 0 putStrLn "Near misses" mapM_ print $ t 1</lang>
- Output:
Answer ([1,0,1,1,0,1,1,0,0,0,1,0],[]) Near misses ([1,1,0,1,0,0,1,1,1,0,0,0],[7]) ([1,1,0,1,0,0,1,0,1,1,0,0],[9]) ([1,1,0,1,0,0,1,0,1,0,0,1],[11]) ([1,0,1,1,0,1,1,0,1,0,0,0],[8]) ([1,0,1,1,0,0,0,1,1,0,0,0],[6]) ([1,0,0,1,0,1,0,1,1,0,0,0],[5]) ([1,0,0,1,0,0,0,1,0,1,1,1],[11]) ([1,0,0,1,0,0,0,0,0,0,0,0],[7]) ([1,0,0,0,1,1,0,0,1,0,1,0],[7]) ([1,0,0,0,1,0,0,1,0,1,1,1],[11]) ([1,0,0,0,1,0,0,1,0,0,1,0],[11]) ([1,0,0,0,1,0,0,1,0,0,0,0],[10]) ([1,0,0,0,1,0,0,0,0,0,0,0],[7]) ([0,0,0,1,0,0,0,1,0,1,1,1],[0]) ([0,0,0,0,1,0,0,1,0,1,1,1],[0]) ([0,0,0,0,1,0,0,1,0,0,1,0],[0])
J
In the following 'apply' is a foreign conjunction: <lang j> apply 128!:2
NB. example
'*:' apply 1 2 3
1 4 9</lang> This enables us to apply strings (left argument) being verbs to the right argument, mostly a noun. <lang j>S=: <;._2 (0 :0) 12&=@# 3=+/@:{.~&_6 2= +/@:{~&1 3 5 7 9 11 4&{=*./@:{~&4 5 6 0=+/@:{~&1 2 3 4=+/@:{~&0 2 4 6 8 10 1=+/@:{~&1 2 6&{=*./@:{~&4 5 6 3=+/@:{.~&6 2=+/@:{~&10 11 1=+/@:{~&6 7 8 4=+/@:{.~&11 )
testall=: (];"1 0<@I.@:(]~:(apply&><))"1) #:@i.@(2&^)@#</lang>
All true <lang j> (#~0=#@{::~&_1"1) testall S ┌───────────────────────┬┐ │1 0 1 1 0 1 1 0 0 0 1 0││ └───────────────────────┴┘</lang> Near misses <lang j> (#~1=#@{::~&_1"1) testall S ┌───────────────────────┬──┐ │0 0 0 0 1 0 0 1 0 0 1 0│0 │ ├───────────────────────┼──┤ │0 0 0 0 1 0 0 1 0 1 1 1│0 │ ├───────────────────────┼──┤ │0 0 0 1 0 0 0 1 0 1 1 1│0 │ ├───────────────────────┼──┤ │1 0 0 0 1 0 0 0 0 0 0 0│7 │ ├───────────────────────┼──┤ │1 0 0 0 1 0 0 1 0 0 0 0│10│ ├───────────────────────┼──┤ │1 0 0 0 1 0 0 1 0 0 1 0│11│ ├───────────────────────┼──┤ │1 0 0 0 1 0 0 1 0 1 1 1│11│ ├───────────────────────┼──┤ │1 0 0 0 1 1 0 0 1 0 1 0│7 │ ├───────────────────────┼──┤ │1 0 0 1 0 0 0 0 0 0 0 0│7 │ ├───────────────────────┼──┤ │1 0 0 1 0 0 0 1 0 1 1 1│11│ ├───────────────────────┼──┤ │1 0 0 1 0 1 0 1 1 0 0 0│5 │ ├───────────────────────┼──┤ │1 0 1 1 0 0 0 1 1 0 0 0│6 │ ├───────────────────────┼──┤ │1 0 1 1 0 1 1 0 1 0 0 0│8 │ ├───────────────────────┼──┤ │1 1 0 1 0 0 1 0 1 0 0 1│11│ ├───────────────────────┼──┤ │1 1 0 1 0 0 1 0 1 1 0 0│9 │ ├───────────────────────┼──┤ │1 1 0 1 0 0 1 1 1 0 0 0│7 │ └───────────────────────┴──┘</lang>
Iterative for all true <lang j> (-N)&{. #: S <:@]^:((]-.@-:(apply&><)"1) (-N)&{.@#:@])^:(_) 2^N=.#S 1 0 1 1 0 1 1 0 0 0 1 0</lang>
Perl 6
<lang perl6>sub infix:<→> ($protasis,$apodosis) { !$protasis or $apodosis }
my @tests = { True }, # (there's no 0th statement)
{ all(.[1..12]) === any(True, False) }, { 3 == [+] .[7..12] }, { 2 == [+] .[2,4...12] }, { .[5] → all .[6,7] }, { none .[2,3,4] }, { 4 == [+] .[1,3...11] }, { one .[2,3] }, { .[7] → all .[5,6] }, { 3 == [+] .[1..6] }, { all .[11,12] }, { one .[7,8,9] }, { 4 == [+] .[1..11] };
my @good; my @bad; my @ugly;
for reverse 0 ..^ 2**12 -> $i {
my @b = $i.fmt("%012b").comb; my @assert = True, @b.map: { .so } my @result = @tests.map: { .(@assert).so } my @s = ( $_ if $_ and @assert[$_] for 1..12 ); if @result eqv @assert {
push @good, "<{@s}> is consistent.";
} else {
my @cons = gather for 1..12 { if @assert[$_] !eqv @result[$_] { take @result[$_] ?? $_ !! "¬$_"; } } my $mess = "<{@s}> implies {@cons}."; if @cons == 1 { push @bad, $mess } else { push @ugly, $mess }
}
}
.say for @good; say "\nNear misses:"; .say for @bad;</lang>
- Output:
<1 3 4 6 7 11> is consistent. Near misses: <1 2 4 7 8 9> implies ¬8. <1 2 4 7 9 10> implies ¬10. <1 2 4 7 9 12> implies ¬12. <1 3 4 6 7 9> implies ¬9. <1 3 4 8 9> implies 7. <1 4 6 8 9> implies ¬6. <1 4 8 10 11 12> implies ¬12. <1 4> implies 8. <1 5 6 9 11> implies 8. <1 5 8 10 11 12> implies ¬12. <1 5 8 11> implies 12. <1 5 8> implies 11. <1 5> implies 8. <4 8 10 11 12> implies 1. <5 8 10 11 12> implies 1. <5 8 11> implies 1.
Python
<lang python> from itertools import product
- from pprint import pprint as pp
constraintinfo = (
(lambda st: len(st) == 12 ,(1, 'This is a numbered list of twelve statements')), (lambda st: sum(st[-6:]) == 3 ,(2, 'Exactly 3 of the last 6 statements are true')), (lambda st: sum(st[1::2]) == 2 ,(3, 'Exactly 2 of the even-numbered statements are true')), (lambda st: (st[5]&st[6]) if st[4] else 1 ,(4, 'If statement 5 is true, then statements 6 and 7 are both true')), (lambda st: sum(st[1:4]) == 0 ,(5, 'The 3 preceding statements are all false')), (lambda st: sum(st[0::2]) == 4 ,(6, 'Exactly 4 of the odd-numbered statements are true')), (lambda st: sum(st[1:3]) == 1 ,(7, 'Either statement 2 or 3 is true, but not both')), (lambda st: (st[4]&st[5]) if st[6] else 1 ,(8, 'If statement 7 is true, then 5 and 6 are both true')), (lambda st: sum(st[:6]) == 3 ,(9, 'Exactly 3 of the first 6 statements are true')), (lambda st: (st[10]&st[11]) ,(10, 'The next two statements are both true')), (lambda st: sum(st[6:9]) == 1 ,(11, 'Exactly 1 of statements 7, 8 and 9 are true')), (lambda st: sum(st[0:11]) == 4 ,(12, 'Exactly 4 of the preceding statements are true')),
)
def printer(st, matches):
if False in matches: print('Missed by one statement: %i, %s' % docs[matches.index(False)]) else: print('Statements:') print(' ' + ', '.join('%i:%s' % (i, 'T' if t else 'F') for i, t in enumerate(st, 1)))
funcs, docs = zip(*constraintinfo)
full, partial = [], []
for st in product( *([(False, True)] * 12) ):
truths = [bool(func(st)) for func in funcs] matches = [s == t for s,t in zip(st, truths)] mcount = sum(matches) if mcount == 12: full.append((st, matches)) elif mcount == 11: partial.append((st, matches))
for stt in full + partial:
printer(*stt)</lang>
- Output:
Full match: 1:T, 2:F, 3:T, 4:T, 5:F, 6:T, 7:T, 8:F, 9:F, 10:F, 11:T, 12:F Missed by one statement: 1, This is a numbered list of twelve statements: 1:F, 2:F, 3:F, 4:F, 5:T, 6:F, 7:F, 8:T, 9:F, 10:F, 11:T, 12:F Missed by one statement: 1, This is a numbered list of twelve statements: 1:F, 2:F, 3:F, 4:F, 5:T, 6:F, 7:F, 8:T, 9:F, 10:T, 11:T, 12:T Missed by one statement: 1, This is a numbered list of twelve statements: 1:F, 2:F, 3:F, 4:T, 5:F, 6:F, 7:F, 8:T, 9:F, 10:T, 11:T, 12:T Missed by one statement: 8, If statement 7 is true, then 5 and 6 are both true: 1:T, 2:F, 3:F, 4:F, 5:T, 6:F, 7:F, 8:F, 9:F, 10:F, 11:F, 12:F Missed by one statement: 11, Exactly 1 of statements 7, 8 and 9 are true: 1:T, 2:F, 3:F, 4:F, 5:T, 6:F, 7:F, 8:T, 9:F, 10:F, 11:F, 12:F Missed by one statement: 12, Exactly 4 of the preceding statements are true: 1:T, 2:F, 3:F, 4:F, 5:T, 6:F, 7:F, 8:T, 9:F, 10:F, 11:T, 12:F Missed by one statement: 12, Exactly 4 of the preceding statements are true: 1:T, 2:F, 3:F, 4:F, 5:T, 6:F, 7:F, 8:T, 9:F, 10:T, 11:T, 12:T Missed by one statement: 8, If statement 7 is true, then 5 and 6 are both true: 1:T, 2:F, 3:F, 4:F, 5:T, 6:T, 7:F, 8:F, 9:T, 10:F, 11:T, 12:F Missed by one statement: 8, If statement 7 is true, then 5 and 6 are both true: 1:T, 2:F, 3:F, 4:T, 5:F, 6:F, 7:F, 8:F, 9:F, 10:F, 11:F, 12:F Missed by one statement: 12, Exactly 4 of the preceding statements are true: 1:T, 2:F, 3:F, 4:T, 5:F, 6:F, 7:F, 8:T, 9:F, 10:T, 11:T, 12:T Missed by one statement: 6, Exactly 4 of the odd-numbered statements are true: 1:T, 2:F, 3:F, 4:T, 5:F, 6:T, 7:F, 8:T, 9:T, 10:F, 11:F, 12:F Missed by one statement: 7, Either statement 2 or 3 is true, but not both: 1:T, 2:F, 3:T, 4:T, 5:F, 6:F, 7:F, 8:T, 9:T, 10:F, 11:F, 12:F Missed by one statement: 9, Exactly 3 of the first 6 statements are true: 1:T, 2:F, 3:T, 4:T, 5:F, 6:T, 7:T, 8:F, 9:T, 10:F, 11:F, 12:F Missed by one statement: 12, Exactly 4 of the preceding statements are true: 1:T, 2:T, 3:F, 4:T, 5:F, 6:F, 7:T, 8:F, 9:T, 10:F, 11:F, 12:T Missed by one statement: 10, The next two statements are both true: 1:T, 2:T, 3:F, 4:T, 5:F, 6:F, 7:T, 8:F, 9:T, 10:T, 11:F, 12:F Missed by one statement: 8, If statement 7 is true, then 5 and 6 are both true: 1:T, 2:T, 3:F, 4:T, 5:F, 6:F, 7:T, 8:T, 9:T, 10:F, 11:F, 12:F