Twelve statements

From Rosetta Code
Jump to: navigation, search
Task
Twelve statements
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.

Contents

[edit] Ada

Works with: Ada 2012

Here is the main program, using a generic package Logic. The expression function introduced by the new standard Ada 2012 are very handy for this task.

with Ada.Text_IO, Logic; 
 
procedure Twelve_Statements is
 
package L is new Logic(Number_Of_Statements => 12); use L;
 
-- formally define the 12 statements as expression function predicates
function P01(T: Table) return Boolean is (T'Length = 12); -- list of 12 statements
function P02(T: Table) return Boolean is (Sum(T(7 .. 12)) = 3); -- three of last six
function P03(T: Table) return Boolean is (Sum(Half(T, Even)) = 2); -- two of the even
function P04(T: Table) return Boolean is (if T(5) then T(6) and T(7)); -- if 5 is true, then ...
function P05(T: Table) return Boolean is
( (not T(2)) and (not T(3)) and (not T(4)) ); -- none of preceding three
function P06(T: Table) return Boolean is (Sum(Half(T, Odd)) = 4); -- four of the odd
function P07(T: Table) return Boolean is (T(2) xor T(3)); -- either 2 or 3, not both
function P08(T: Table) return Boolean is (if T(7) then T(5) and T(6)); -- if 7 is true, then ...
function P09(T: Table) return Boolean is (Sum(T(1 .. 6)) = 3); -- three of first six
function P10(T: Table) return Boolean is (T(11) and T(12)); -- next two
function P11(T: Table) return Boolean is (Sum(T(7..9)) = 1); -- one of 7, 8, 9
function P12(T: Table) return Boolean is (Sum(T(1 .. 11)) = 4); -- four of the preding
 
-- define a global list of statements
Statement_List: constant Statements :=
(P01'Access, P02'Access, P03'Access, P04'Access, P05'Access, P06'Access,
P07'Access, P08'Access, P09'Access, P10'Access, P11'Access, P12'Access);
 
-- try out all 2^12 possible choices for the table
procedure Try(T: Table; Fail: Natural; Idx: Indices'Base := Indices'First) is
 
procedure Print_Table(T: Table) is
use Ada.Text_IO;
begin
Put(" ");
if Fail > 0 then
Put("(wrong at");
for J in T'Range loop
if Statement_List(J)(T) /= T(J) then
Put(Integer'Image(J) & (if J < 10 then ") " else ") "));
end if;
end loop;
end if;
if T = (1..12 => False) then
Put_Line("All false!");
else
Put("True are");
for J in T'Range loop
if T(J) then
Put(Integer'Image(J));
end if;
end loop;
New_Line;
end if;
end Print_Table;
 
Wrong_Entries: Natural := 0;
 
begin
if Idx <= T'Last then
Try(T(T'First .. Idx-1) & False & T(Idx+1 .. T'Last), Fail, Idx+1);
Try(T(T'First .. Idx-1) & True & T(Idx+1 .. T'Last), Fail, Idx+1);
else -- now Index > T'Last and we have one of the 2^12 choices to test
for J in T'Range loop
if Statement_List(J)(T) /= T(J) then
Wrong_Entries := Wrong_Entries + 1;
end if;
end loop;
if Wrong_Entries = Fail then
Print_Table(T);
end if;
end if;
end Try;
 
begin
Ada.Text_IO.Put_Line("Exact hits:");
Try(T => (1..12 => False), Fail => 0);
Ada.Text_IO.New_Line;
Ada.Text_IO.Put_Line("Near Misses:");
Try(T => (1..12 => False), Fail => 1);
end Twelve_Statements;
Output:
Exact hits:
    True are 1 3 4 6 7 11

Near Misses:
    (wrong at 1)  True are 5 8 11
    (wrong at 1)  True are 5 8 10 11 12
    (wrong at 1)  True are 4 8 10 11 12
    (wrong at 8)  True are 1 5
    (wrong at 11) True are 1 5 8
    (wrong at 12) True are 1 5 8 11
    (wrong at 12) True are 1 5 8 10 11 12
    (wrong at 8)  True are 1 5 6 9 11
    (wrong at 8)  True are 1 4
    (wrong at 12) True are 1 4 8 10 11 12
    (wrong at 6)  True are 1 4 6 8 9
    (wrong at 7)  True are 1 3 4 8 9
    (wrong at 9)  True are 1 3 4 6 7 9
    (wrong at 12) True are 1 2 4 7 9 12
    (wrong at 10) True are 1 2 4 7 9 10
    (wrong at 8)  True are 1 2 4 7 8 9

Here is the definition the package Logic:

generic
Number_Of_Statements: Positive;
package Logic is
 
--types
subtype Indices is Natural range 1 .. Number_Of_Statements;
type Table is array(Indices range <>) of Boolean;
type Predicate is access function(T: Table) return Boolean;
type Statements is array(Indices) of Predicate;
type Even_Odd is (Even, Odd);
 
-- convenience functions
function Sum(T: Table) return Natural;
function Half(T: Table; Which: Even_Odd) return Table;
 
end Logic;

And here is the implementation of the "convenience functions" in Logic:

package body Logic is   
 
function Sum(T: Table) return Natural is
Result: Natural := 0;
begin
for I in T'Range loop
if T(I) then
Result := Result + 1;
end if;
end loop;
return Result;
end Sum;
 
function Half(T: Table; Which: Even_Odd) return Table is
Result: Table(T'Range);
Last: Natural := Result'First - 1;
begin
for I in T'Range loop
if I mod 2 = (if (Which=Odd) then 1 else 0) then
Last := Last+1;
Result(Last) := T(I);
end if;
end loop;
return Result(Result'First .. Last);
end Half;
 
end Logic;

[edit] AutoHotkey

Just like the Python version, this code uses bruteforce (4096 iterations) to set 12 flags and test all statements on each iteration. If the proposed flags match the results after validating each statement, we have the solution. The code shows all cases where we have at least S-1 matches (where S = 12 statements).

; Note: the original puzzle provides 12 statements and starts with
; "Given the following twelve statements...", so the first statement
; should ignore the F1 flag and always be true (see "( N == 1 )").
 
S := 12 ; number of statements
Output := ""
Loop, % 2**S {
;;If !Mod(A_Index,100) ;; optional 'if' to show the loop progress
;; ToolTip, Index: %A_Index%
SetFlags(A_Index-1), Current := "", Count := 0
Loop, %S%
R := TestStatement(A_Index), Current .= " " R, Count += (R == F%A_Index%)
If ( Count >= S-1 )
Output .= Count " ->" Current "`n"
If ( Count = S )
Solution := "`nSolution = " Current
}
ToolTip
MsgBox, % Output . Solution
Return
 
;-------------------------------------------------------------------------------------
 
SetFlags(D) {
Local I
Loop, %S%
I := S-A_Index+1 , F%I% := (D >> (S-A_Index)) & 1
}
 
;-------------------------------------------------------------------------------------
 
TestStatement(N) {
Local I, C := 0
If ( N == 1 ) ; This is a numbered list of twelve statements.
Return ( S == 12 ) ; should always be true
If ( N == 2 ) { ; Exactly 3 of the last 6 statements are true.
Loop, 6
I := S-A_Index+1 , C += F%I%
Return ( C == 3 )
}
If ( N == 3 ) { ; Exactly 2 of the even-numbered statements are true.
Loop, %S%
C += ( !Mod(A_Index,2) & F%A_Index% )
Return ( C == 2 )
}
If ( N == 4 ) ; If statement 5 is true, then statements 6 and 7 are both true.
Return ( F5 ? F6 & F7 : 1 )
If ( N == 5 ) { ; The 3 preceding statements are all false.
Loop, 3
I := N-A_Index , C += F%I%
Return ( C == 0 )
}
If ( N == 6 ) { ; Exactly 4 of the odd-numbered statements are true.
Loop, %S%
C += ( !!Mod(A_Index,2) & F%A_Index% )
Return ( C == 4 )
}
If ( N == 7 ) ; Either statement 2 or 3 is true, but not both.
Return ( F2 ^ F3 )
If ( N == 8 ) ; If statement 7 is true, then 5 and 6 are both true.
Return ( F7 ? F5 & F6 : 1 )
If ( N == 9 ) { ; Exactly 3 of the first 6 statements are true.
Loop, 6
C += F%A_Index%
Return ( C == 3 )
}
If ( N == 10 ) ; The next two statements are both true.
Return ( F11 & F12 )
If ( N == 11 ) ; Exactly 1 of statements 7, 8 and 9 are true
Return ( F7+F8+F9 == 1 )
If ( N == 12 ) { ; Exactly 4 of the preceding statements are true
Loop, % N-1
C += F%A_Index%
Return ( C == 4 )
}
}
Output:
11 -> 1 0 0 1 0 0 0 1 0 0 0 0
11 -> 1 0 0 0 1 0 0 1 0 0 0 0
11 -> 1 0 0 0 1 0 0 1 0 0 1 0
11 -> 1 0 1 1 0 1 1 0 0 0 0 0
11 -> 1 0 1 1 0 0 1 1 1 0 0 0
11 -> 1 0 0 1 0 0 0 1 1 0 0 0
11 -> 1 1 0 1 0 0 1 0 1 0 0 0
11 -> 1 1 0 1 0 0 1 0 1 0 0 0
12 -> 1 0 1 1 0 1 1 0 0 0 1 0
11 -> 1 0 0 0 1 0 0 1 0 0 1 0
11 -> 1 0 0 0 1 0 0 1 0 0 1 1
11 -> 1 0 0 0 1 1 0 1 1 0 1 0
11 -> 1 1 0 1 0 0 1 0 1 0 0 0
11 -> 1 0 0 1 0 0 0 1 0 1 1 1
11 -> 1 0 0 1 0 0 0 1 0 1 1 0
11 -> 1 0 0 0 1 0 0 1 0 1 1 1
11 -> 1 0 0 0 1 0 0 1 0 1 1 0

Solution =  1 0 1 1 0 1 1 0 0 0 1 0

[edit] BBC BASIC

      nStatements% = 12
DIM Pass%(nStatements%), T%(nStatements%)
 
FOR try% = 0 TO 2^nStatements%-1
 
REM Postulate answer:
FOR stmt% = 1 TO 12
T%(stmt%) = (try% AND 2^(stmt%-1)) <> 0
NEXT
 
REM Test consistency:
Pass%(1) = T%(1) = (nStatements% = 12)
Pass%(2) = T%(2) = ((T%(7)+T%(8)+T%(9)+T%(10)+T%(11)+T%(12)) = -3)
Pass%(3) = T%(3) = ((T%(2)+T%(4)+T%(6)+T%(8)+T%(10)+T%(12)) = -2)
Pass%(4) = T%(4) = ((NOT T%(5) OR (T%(6) AND T%(7))))
Pass%(5) = T%(5) = (NOT T%(2) AND NOT T%(3) AND NOT T%(4))
Pass%(6) = T%(6) = ((T%(1)+T%(3)+T%(5)+T%(7)+T%(9)+T%(11)) = -4)
Pass%(7) = T%(7) = ((T%(2) EOR T%(3)))
Pass%(8) = T%(8) = ((NOT T%(7) OR (T%(5) AND T%(6))))
Pass%(9) = T%(9) = ((T%(1)+T%(2)+T%(3)+T%(4)+T%(5)+T%(6)) = -3)
Pass%(10) = T%(10) = (T%(11) AND T%(12))
Pass%(11) = T%(11) = ((T%(7)+T%(8)+T%(9)) = -1)
Pass%(12) = T%(12) = ((T%(1)+T%(2)+T%(3)+T%(4)+T%(5)+T%(6) + \
\ T%(7)+T%(8)+T%(9)+T%(10)+T%(11)) = -4)
 
CASE SUM(Pass%()) OF
WHEN -11:
PRINT "Near miss with statements ";
FOR stmt% = 1 TO 12
IF T%(stmt%) PRINT ; stmt% " ";
IF NOT Pass%(stmt%) miss% = stmt%
NEXT
PRINT "true (failed " ;miss% ")."
WHEN -12:
PRINT "Solution! with statements ";
FOR stmt% = 1 TO 12
IF T%(stmt%) PRINT ; stmt% " ";
NEXT
PRINT "true."
ENDCASE
 
NEXT try%
END

Output:

Near miss with statements 1 4 true (failed 8).
Near miss with statements 1 5 true (failed 8).
Near miss with statements 1 5 8 true (failed 11).
Near miss with statements 1 3 4 6 7 9 true (failed 9).
Near miss with statements 1 3 4 8 9 true (failed 7).
Near miss with statements 1 4 6 8 9 true (failed 6).
Near miss with statements 1 2 4 7 8 9 true (failed 8).
Near miss with statements 1 2 4 7 9 10 true (failed 10).
Solution! with statements 1 3 4 6 7 11 true.
Near miss with statements 5 8 11 true (failed 1).
Near miss with statements 1 5 8 11 true (failed 12).
Near miss with statements 1 5 6 9 11 true (failed 8).
Near miss with statements 1 2 4 7 9 12 true (failed 12).
Near miss with statements 4 8 10 11 12 true (failed 1).
Near miss with statements 1 4 8 10 11 12 true (failed 12).
Near miss with statements 5 8 10 11 12 true (failed 1).
Near miss with statements 1 5 8 10 11 12 true (failed 12).

[edit] Bracmat

(
( number
= n done ntest oldFT
.  !arg:(?done.(=?ntest).?oldFT)
& 0:?n
& (  !done
 :  ?
( !ntest
. !oldFT&1+!n:?n&~
)
 ?
| !n
)
)
& ( STATEMENTS
= ( (1."This is a numbered list of twelve statements.")
. 1
. (
= n nr done toDo
.  !arg:(?done.?toDo)
& 0:?n
& whl
' ( !done:(?nr.?) ?done
& 1+!n:!nr:?n
)
& whl
' ( !toDo:((?nr.?).?) ?toDo
& 1+!n:!nr:?n
)
& (!n:12&true|false)
)
)
( (2."Exactly 3 of the last 6 statements are true.")
. end
. (
= done toDo lastSix
.  !arg:(?done.?toDo)
& !done:? [-7 ?lastSix
& ( number$(!lastSix.(=?).true):3
& true
| false
)
)
)
( (3."Exactly 2 of the even-numbered statements are true.")
. end
. (
= done toDo ii
.  !arg:(?done.?toDo)
& ( number
$ ( !done
. (=?ii&!ii*1/2:~/)
. true
)
 : 2
& true
| false
)
)
)
( (4."If statement 5 is true, then statements 6 and 7 are both true.")
. 7
. (
= done toDo
.  !arg:(?done.?toDo)
& (  !done
 : ( ? (5.false) ?
|  ? (6.true) ?
 : ? (7.true) ?
)
& true
| false
)
)
)
( (5."The 3 preceding statements are all false.")
. 5
. (
= done toDo
.  !arg:(?done.?toDo)
& (  !done
 :  ?
(?.false)
(?.false)
(?.false)
(?.?)
& true
| false
)
)
)
( (6."Exactly 4 of the odd-numbered statements are true.")
. end
. (
= done toDo i
.  !arg:(?done.?toDo)
& ( number
$ ( !done
. (=?i&!i*1/2:/)
. true
)
 : 4
& true
| false
)
)
)
( (7."Either statement 2 or 3 is true, but not both.")
. 7
. (
= done toDo
.  !arg:(?done.?toDo)
& ( number
$ (!done.(=2|3).true)
 : 1
& true
| false
)
)
)
( (8."If statement 7 is true, then 5 and 6 are both true.")
. 8
. (
= done toDo
.  !arg:(?done.?toDo)
& (  !done
 : ( ? (7.false) ?
|  ? (5.true) ?
 : ? (6.true) ?
)
& true
| false
)
)
)
( (9."Exactly 3 of the first 6 statements are true.")
. 9
. (
= done toDo firstSix
.  !arg:(?done.?toDo)
& !done:?firstSix [6 ?
& ( number$(!firstSix.(=?).true):3
& true
| false
)
)
)
( (10."The next two statements are both true.")
. 12
. (
= done toDo
.  !arg:(?done.?toDo)
& (  !done:? (?.true) (?.true)
& true
| false
)
)
)
( (11."Exactly 1 of statements 7, 8 and 9 are true.")
. 11
. (
= done toDo
.  !arg:(?done.?toDo)
& ( number
$ ( !done
. (=7|8|9)
. true
)
 : 1
& true
| false
)
)
)
( (12."Exactly 4 of the preceding statements are true.")
. 12
. (
= done toDo preceding
.  !arg:(?done.?toDo)
& !done:?preceding (?.?)
& ( number$(!preceding.(=?).true):4
& true
| false
)
)
)
)
& ( TestTruth
= done toDo postponedTests testToBePostponed
, n when test FT oldFT A Z text
, postponedTest testNow
.  !arg:(?done.?toDo.?postponedTests)
& (  !toDo:
& "We have come to the end of the list of tests.
Perform any tests that had to be postponed until now."
& whl
' (  !postponedTests
 : (?.?oldFT.(=?postponedTest)) ?A
& postponedTest$(!done.):!oldFT
& !A:?postponedTests
)
& !postponedTests:
& out$("Solution:" !done)
& ~
|  !toDo
 : ((?n.?text).?when.(=?test)) ?toDo
& "'false' and 'true' are just two symbols, not 'boolean values'.
You can choose other symbols if you like.
The program first guesses the first symbol and assigns it to the variable FT.
After backtracking, the second symbol is guessed and assigned to FT.
This is done for each statement."
& false true
 :  ?
 %@?FT
( ?
& 1+!guesses:?guesses
& (!n.!FT):?testNow
& "Do all tests that had to be postponed until now, unless one of those tests
fails. Remove the successful tests from the list of postponed tests."
& whl
' (  !postponedTests
 :  ?A
(!n.?oldFT.(=?postponedTest))
 ?Z
& postponedTest$(!done !testNow.!toDo)
 : !oldFT
& !A !Z:?postponedTests
)
& "Check that all tests that had to be postponed until now are removed from
the list of postponed tests. Only then go on with looking at testing
the current statement. Backtrack if a test failed."
& !postponedTests:~(? (!n.?) ?)
& (  !when:>!n
& "The current statement cannot be tested right now. Postpone it to
the earliest coming statement where the current statement can be
tested.
(The earliest statement, denoted by 'when', is computed manually.)"
& (!when.!FT.'$test):?testToBePostponed
| "No need to postpone. Test the current statement now."
& :?testToBePostponed
& "If the test fails, backtrack. If it succeeds, go on to the next
statement."
& test$(!done !testNow.!toDo):!FT
)
& "So far so good. Test the next statements. (recursively)"
& TestTruth
$ ( !done !testNow
. !toDo
. !testToBePostponed !postponedTests
)
)
)
)
& 0:?guesses
& TestTruth$(.!STATEMENTS.)
| out
$ ( str
$ ( "That's it. I made "
 !guesses
" true/false guesses in all. (A brute force method needs 2^12="
2^12
" guesses."
)
)
);

Output:

  Solution:
  (1.true)
  (2.false)
  (3.true)
  (4.true)
  (5.false)
  (6.true)
  (7.true)
  (8.false)
  (9.false)
  (10.false)
  (11.true)
  (12.false)
That's it. I made 220 true/false guesses in all. (A brute force method needs 2^12=4096 guesses.

[edit] D

import std.stdio, std.algorithm, std.range, std.functional;
 
immutable texts = [
"this is a numbered list of twelve statements",
"exactly 3 of the last 6 statements are true",
"exactly 2 of the even-numbered statements are true",
"if statement 5 is true, then statements 6 and 7 are both true",
"the 3 preceding statements are all false",
"exactly 4 of the odd-numbered statements are true",
"either statement 2 or 3 is true, but not both",
"if statement 7 is true, then 5 and 6 are both true",
"exactly 3 of the first 6 statements are true",
"the next two statements are both true",
"exactly 1 of statements 7, 8 and 9 are true",
"exactly 4 of the preceding statements are true"];
 
immutable pure @safe /*@nogc*/ bool function(in bool[])[12] predicates = [
s => s.length == 12,
s => s[$ - 6 .. $].sum == 3,
s => s.dropOne.stride(2).sum == 2,
s => s[4] ? (s[5] && s[6]) : true,
s => s[1 .. 4].sum == 0,
s => s.stride(2).sum == 4,
s => s[1 .. 3].sum == 1,
s => s[6] ? (s[4] && s[5]) : true,
s => s[0 .. 6].sum == 3,
s => s[10] && s[11],
s => s[6 .. 9].sum == 1,
s => s[0 .. 11].sum == 4];
 
void main() {
enum nStats = predicates.length;
 
foreach (immutable n; 0 .. 2 ^^ nStats) {
bool[nStats] st, matches;
nStats.iota.map!(i => !!(n & (2 ^^ i))).copy(st[]);
st[].zip(predicates[].map!(f => f(st)))
.map!(s_t => s_t[0] == s_t[1]).copy(matches[]);
if (matches[].sum >= nStats - 1) {
if (matches[].all)
">>> Solution:".writeln;
else
writefln("Missed by statement: %d",
matches[].countUntil(false) + 1);
writefln("%-(%s %)", st[].map!q{ "FT"[a] });
}
}
}
Output:
Missed by statement: 8
T F F T F F F F F F F F
Missed by statement: 8
T F F F T F F F F F F F
Missed by statement: 11
T F F F T F F T F F F F
Missed by statement: 9
T F T T F T T F T F F F
Missed by statement: 7
T F T T F F F T T F F F
Missed by statement: 6
T F F T F T F T T F F F
Missed by statement: 8
T T F T F F T T T F F F
Missed by statement: 10
T T F T F F T F T T F F
>>> Solution:
T F T T F T T F F F T F
Missed by statement: 1
F F F F T F F T F F T F
Missed by statement: 12
T F F F T F F T F F T F
Missed by statement: 8
T F F F T T F F T F T F
Missed by statement: 12
T T F T F F T F T F F T
Missed by statement: 1
F F F T F F F T F T T T
Missed by statement: 12
T F F T F F F T F T T T
Missed by statement: 1
F F F F T F F T F T T T
Missed by statement: 12
T F F F T F F T F T T T

[edit] Forth

Forth is excellently suited to solve this, because it has excellent support for manipulating bitpatterns.

: lastbit                              ( n1 -- n2)
dup if 1 swap begin dup 1 <> while swap 1+ swap 1 rshift repeat drop then
;
 
: bit 1 swap lshift and 0<> ; ( n1 n2 -- f)
: bitcount 0 swap begin dup while dup 1- and swap 1+ swap repeat drop ;
 
12 constant #stat \ number of statements
\ encoding of the statements
: s1 >r #stat 12 = r> 0 bit = ; \ heavy use of binary
: s2 >r r@ 4032 and bitcount 3 = r> 1 bit = ;
: s3 >r r@ 2730 and bitcount 2 = r> 2 bit = ;
: s4 >r r@ 4 bit 0= 96 r@ over and = or r> 3 bit = ;
: s5 >r r@ 14 and 0= r> 4 bit = ;
: s6 >r r@ 1365 and bitcount 4 = r> 5 bit = ;
: s7 >r r@ 1 bit r@ 2 bit xor r> 6 bit = ;
: s8 >r r@ 6 bit 0= 48 r@ over and = or r> 7 bit = ;
: s9 >r r@ 63 and bitcount 3 = r> 8 bit = ;
: s10 >r 3072 r@ over and = r> 9 bit = ;
: s11 >r r@ 448 and bitcount 1 = r> 10 bit = ;
: s12 >r r@ 2047 and bitcount 4 = r> 11 bit = ;
: list #stat 0 do dup i bit if i 1+ . then loop drop ;
 
: nearmiss? \ do we have a near miss?
over #stat 1- = if ( true-pattern #true stat-pattern)
." Near miss with statements " dup list ." true (failed "
>r over invert 1 #stat lshift 1- and lastbit 0 .r ." )" cr r>
then \ extract the failed statement
;
\ have we found a solution?
: solution? ( true-pattern #true stat-pattern)
over #stat = if ." Solution! with statements " dup list ." true." cr then
;
 
: 12statements \ test the twelve patterns
1 #stat lshift 0 do \ create another bit pattern
i s12 2* i s11 + 2* i s10 + 2* i s9 + 2* i s8 + 2* i s7 + 2*
i s6 + 2* i s5 + 2* i s4 + 2* i s3 + 2* i s2 + 2* i s1 +
abs dup bitcount i solution? nearmiss? drop drop drop
loop \ count number of bytes and evaluate
;
 
12statements

Output:

Near miss with statements 1 4 true (failed 8)
Near miss with statements 1 5 true (failed 8)
Near miss with statements 1 5 8 true (failed 11)
Near miss with statements 1 3 4 6 7 9 true (failed 9)
Near miss with statements 1 3 4 8 9 true (failed 7)
Near miss with statements 1 4 6 8 9 true (failed 6)
Near miss with statements 1 2 4 7 8 9 true (failed 8)
Near miss with statements 1 2 4 7 9 10 true (failed 10)
Solution! with statements 1 3 4 6 7 11 true.
Near miss with statements 5 8 11 true (failed 1)
Near miss with statements 1 5 8 11 true (failed 12)
Near miss with statements 1 5 6 9 11 true (failed 8)
Near miss with statements 1 2 4 7 9 12 true (failed 12)
Near miss with statements 4 8 10 11 12 true (failed 1)
Near miss with statements 1 4 8 10 11 12 true (failed 12)
Near miss with statements 5 8 10 11 12 true (failed 1)
Near miss with statements 1 5 8 10 11 12 true (failed 12)
 ok

[edit] 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
}
}
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

[edit] Groovy

Solution:

enum Rule {
r01( 1, { r()*.num == (1..12) }),
r02( 2, { r(7..12).count { it.truth } == 3 }),
r03( 3, { r(2..12, 2).count { it.truth } == 2 }),
r04( 4, { r(5).truth ? r(6).truth && r(7).truth : true }),
r05( 5, { r(2..4).count { it.truth } == 0 }),
r06( 6, { r(1..11, 2).count { it.truth } == 4 }),
r07( 7, { r(2).truth != r(3).truth }),
r08( 8, { r(7).truth ? r(5).truth && r(6).truth : true }),
r09( 9, { r(1..6).count { it.truth } == 3 }),
r10(10, { r(11).truth && r(12).truth }),
r11(11, { r(7..9).count { it.truth } == 1 }),
r12(12, { r(1..11).count { it.truth } == 4 });
 
final int num
final Closure statement
boolean truth
 
static final List<Rule> rules = [ null, r01, r02, r03, r04, r05, r06, r07, r08, r09, r10, r11, r12]
 
private Rule(num, statement) {
this.num = num
this.statement = statement
}
 
public static Rule r(int index) { rules[index] }
public static List<Rule> r() { rules[1..12] }
public static List<Rule> r(List<Integer> indices) { rules[indices] }
public static List<Rule> r(IntRange indices) { rules[indices] }
public static List<Rule> r(IntRange indices, int step) { r(indices.step(step)) }
 
public static void setAllTruth(int bits) {
(1..12).each { r(it).truth = !(bits & (1 << (12 - it))) }
}
 
public static void evaluate() {
def nearMisses = [:]
(0..<(2**12)).each { i ->
setAllTruth(i)
def truthCandidates = r().findAll { it.truth }
def truthMatchCount = r().count { it.statement() == it.truth }
if (truthMatchCount == 12) {
println ">Solution< ${truthCandidates*.num}"
} else if (truthMatchCount == 11) {
def miss = (1..12).find { r(it).statement() != r(it).truth }
nearMisses << [(truthCandidates): miss]
}
}
nearMisses.each { truths, miss ->
printf ("Near Miss: %-21s (failed %2d)\n", "${truths*.num}", miss)
}
}
}
 
Rule.evaluate()

Output:

>Solution< [1, 3, 4, 6, 7, 11]
Near Miss: [1, 2, 4, 7, 8, 9]    (failed  8)
Near Miss: [1, 2, 4, 7, 9, 10]   (failed 10)
Near Miss: [1, 2, 4, 7, 9, 12]   (failed 12)
Near Miss: [1, 3, 4, 6, 7, 9]    (failed  9)
Near Miss: [1, 3, 4, 8, 9]       (failed  7)
Near Miss: [1, 4, 6, 8, 9]       (failed  6)
Near Miss: [1, 4, 8, 10, 11, 12] (failed 12)
Near Miss: [1, 4]                (failed  8)
Near Miss: [1, 5, 6, 9, 11]      (failed  8)
Near Miss: [1, 5, 8, 10, 11, 12] (failed 12)
Near Miss: [1, 5, 8, 11]         (failed 12)
Near Miss: [1, 5, 8]             (failed 11)
Near Miss: [1, 5]                (failed  8)
Near Miss: [4, 8, 10, 11, 12]    (failed  1)
Near Miss: [5, 8, 10, 11, 12]    (failed  1)
Near Miss: [5, 8, 11]            (failed  1)


[edit] Haskell

Shows answers with 1 for true, followed by list of indices of contradicting elements in each set of 1/0s (index is 0-based).

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
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])

[edit] J

In the following 'apply' is the foreign conjunction:

   apply
128!:2
 
NB. example
'*:' apply 1 2 3
1 4 9

This enables us to apply strings (left argument) being verbs to the right argument, mostly a noun.

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&^)@#

The output follows the Haskell convention: true/false bitstring followed by the index of a contradiction

All true

   (#~0=#@{::~&_1"1) testall S
┌───────────────────────┬┐
1 0 1 1 0 1 1 0 0 0 1 0││
└───────────────────────┴┘

Near misses

   (#~1=#@{::~&_1"1) testall S
┌───────────────────────┬──┐
0 0 0 0 1 0 0 1 0 0 1 00
├───────────────────────┼──┤
0 0 0 0 1 0 0 1 0 1 1 10
├───────────────────────┼──┤
0 0 0 1 0 0 0 1 0 1 1 10
├───────────────────────┼──┤
1 0 0 0 1 0 0 0 0 0 0 07
├───────────────────────┼──┤
1 0 0 0 1 0 0 1 0 0 0 010
├───────────────────────┼──┤
1 0 0 0 1 0 0 1 0 0 1 011
├───────────────────────┼──┤
1 0 0 0 1 0 0 1 0 1 1 111
├───────────────────────┼──┤
1 0 0 0 1 1 0 0 1 0 1 07
├───────────────────────┼──┤
1 0 0 1 0 0 0 0 0 0 0 07
├───────────────────────┼──┤
1 0 0 1 0 0 0 1 0 1 1 111
├───────────────────────┼──┤
1 0 0 1 0 1 0 1 1 0 0 05
├───────────────────────┼──┤
1 0 1 1 0 0 0 1 1 0 0 06
├───────────────────────┼──┤
1 0 1 1 0 1 1 0 1 0 0 08
├───────────────────────┼──┤
1 1 0 1 0 0 1 0 1 0 0 111
├───────────────────────┼──┤
1 1 0 1 0 0 1 0 1 1 0 09
├───────────────────────┼──┤
1 1 0 1 0 0 1 1 1 0 0 07
└───────────────────────┴──┘

Iterative for all true
In fact a repeat while true construction: x f^:(p)^:_ y

   (-N)&{. #: S <:@]^:((]-.@-:(apply&><)"1) (-N)&{.@#:@])^:(_) 2^N=.#S
1 0 1 1 0 1 1 0 0 0 1 0


[edit] Java

The following Java code uses brute force. It tries to translate the logical statements as naturally as possible. The run time is almost zero.

 
public class LogicPuzzle
{
boolean S[] = new boolean[13];
int Count = 0;
 
public boolean check2 ()
{
int count = 0;
for (int k = 7; k <= 12; k++)
if (S[k]) count++;
return S[2] == (count == 3);
}
 
public boolean check3 ()
{
int count = 0;
for (int k = 2; k <= 12; k += 2)
if (S[k]) count++;
return S[3] == (count == 2);
}
 
public boolean check4 ()
{
return S[4] == ( !S[5] || S[6] && S[7]);
}
 
public boolean check5 ()
{
return S[5] == ( !S[2] && !S[3] && !S[4]);
}
 
public boolean check6 ()
{
int count = 0;
for (int k = 1; k <= 11; k += 2)
if (S[k]) count++;
return S[6] == (count == 4);
}
 
public boolean check7 ()
{
return S[7] == ((S[2] || S[3]) && !(S[2] && S[3]));
}
 
public boolean check8 ()
{
return S[8] == ( !S[7] || S[5] && S[6]);
}
 
public boolean check9 ()
{
int count = 0;
for (int k = 1; k <= 6; k++)
if (S[k]) count++;
return S[9] == (count == 3);
}
 
public boolean check10 ()
{
return S[10] == (S[11] && S[12]);
}
 
public boolean check11 ()
{
int count = 0;
for (int k = 7; k <= 9; k++)
if (S[k]) count++;
return S[11] == (count == 1);
}
 
public boolean check12 ()
{
int count = 0;
for (int k = 1; k <= 11; k++)
if (S[k]) count++;
return S[12] == (count == 4);
}
 
public void check ()
{
if (check2() && check3() && check4() && check5() && check6()
&& check7() && check8() && check9() && check10() && check11()
&& check12())
{
for (int k = 1; k <= 12; k++)
if (S[k]) System.out.print(k + " ");
System.out.println();
Count++;
}
}
 
public void recurseAll (int k)
{
if (k == 13)
check();
else
{
S[k] = false;
recurseAll(k + 1);
S[k] = true;
recurseAll(k + 1);
}
}
 
public static void main (String args[])
{
LogicPuzzle P = new LogicPuzzle();
P.S[1] = true;
P.recurseAll(2);
System.out.println();
System.out.println(P.Count + " Solutions found.");
}
}
 
Output:
1 3 4 6 7 11 

1 Solutions found.

[edit] Mathematica

Print["Answer:\n", Column@Cases[#, {s_, 0} :> s], "\nNear misses:\n", 
Column@Cases[#, {s_, 1} :> s]] &[{#,
Count[Boole /@ {Length@# == 12, Total@#[[7 ;;]] == 3,
Total@#[[2 ;; 12 ;; 2]] == 2, #[[5]] (#[[6]] + #[[7]] - 2) ==
0, Total@#[[2 ;; 4]] == 0,
Total@#[[1 ;; 11 ;; 2]] == 4, #[[2]] + #[[3]] ==
1, #[[7]] (#[[5]] + #[[6]] - 2) == 0,
Total@#[[;; 6]] == 3, #[[11]] + #[[12]] == 2,
Total@#[[7 ;; 9]] == 1, Total@#[[;; 11]] == 4} - #,
Except[0]]} & /@ Tuples[{1, 0}, 12]]
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}
{1,1,0,1,0,0,1,0,1,1,0,0}
{1,1,0,1,0,0,1,0,1,0,0,1}
{1,0,1,1,0,1,1,0,1,0,0,0}
{1,0,1,1,0,0,0,1,1,0,0,0}
{1,0,0,1,0,1,0,1,1,0,0,0}
{1,0,0,1,0,0,0,1,0,1,1,1}
{1,0,0,1,0,0,0,0,0,0,0,0}
{1,0,0,0,1,1,0,0,1,0,1,0}
{1,0,0,0,1,0,0,1,0,1,1,1}
{1,0,0,0,1,0,0,1,0,0,1,0}
{1,0,0,0,1,0,0,1,0,0,0,0}
{1,0,0,0,1,0,0,0,0,0,0,0}
{0,0,0,1,0,0,0,1,0,1,1,1}
{0,0,0,0,1,0,0,1,0,1,1,1}
{0,0,0,0,1,0,0,1,0,0,1,0}

[edit] Perl

use List::Util 'sum';
 
my @condition = (
sub { 0 }, # dummy sub for index 0
sub { 13==@_ },
sub { 3==sum @_[7..12] },
sub { 2==sum @_[2,4,6,8,10,12] },
sub { $_[5] ? ($_[6] and $_[7]) : 1 },
sub { !$_[2] and !$_[3] and !$_[4] },
sub { 4==sum @_[1,3,5,7,9,11] },
sub { $_[2]==1-$_[3] },
sub { $_[7] ? ($_[5] and $_[6]) : 1 },
sub { 3==sum @_[1..6] },
sub { 2==sum @_[11..12] },
sub { 1==sum @_[7,8,9] },
sub { 4==sum @_[1..11] },
);
 
sub miss {
return grep { $condition[$_]->(@_) != $_[$_] } 1..12;
}
 
for (0..2**12-1) {
my @truth = split //, sprintf "0%012b", $_;
my @no = miss @truth;
print "Solution: true statements are ", join( " ", grep { $truth[$_] } 1..12), "\n" if 0 == @no;
print "1 miss (",$no[0],"): true statements are ", join( " ", grep { $truth[$_] } 1..12), "\n" if 1 == @no;
}
 
Output:
1 miss (1): true statements are 5 8 11
1 miss (1): true statements are 5 8 10 11 12
1 miss (1): true statements are 4 8 10 11 12
1 miss (8): true statements are 1 5
1 miss (11): true statements are 1 5 8
1 miss (12): true statements are 1 5 8 11
1 miss (12): true statements are 1 5 8 10 11 12
1 miss (8): true statements are 1 5 6 9 11
1 miss (8): true statements are 1 4
1 miss (12): true statements are 1 4 8 10 11 12
1 miss (6): true statements are 1 4 6 8 9
1 miss (7): true statements are 1 3 4 8 9
Solution: true statements are 1 3 4 6 7 11
1 miss (9): true statements are 1 3 4 6 7 9
1 miss (12): true statements are 1 2 4 7 9 12
1 miss (10): true statements are 1 2 4 7 9 10
1 miss (8): true statements are 1 2 4 7 8 9

[edit] Perl 6

sub infix:<> ($protasis,$apodosis) { !$protasis or $apodosis }
 
my @tests = { True }, # (there's no 0th statement)
{ .end == 12 and 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;
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.

[edit] Prolog

Works with SWI-Prolog and library(clpfd).

puzzle :-
% 1. This is a numbered list of twelve statements.
L = [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12],
L ins 0..1,
element(1, L, 1),
 
% 2. Exactly 3 of the last 6 statements are true.
A2 #<==> A7 + A8 + A9 + A10 + A11 + A12 #= 3,
 
% 3. Exactly 2 of the even-numbered statements are true.
A3 #<==> A2 + A4 + A6 + A8 + A10 + A12 #= 2,
 
% 4. If statement 5 is true, then statements 6 and 7 are both true.
A4 #<==> (A5 #==> (A6 #/\ A7)),
 
% 5. The 3 preceding statements are all false.
A5 #<==> A2 + A3 + A4 #= 0,
 
% 6. Exactly 4 of the odd-numbered statements are true.
A6 #==> A1 + A3 + A5 + A7 + A9 + A11 #= 4,
 
% 7. Either statement 2 or 3 is true, but not both.
A7 #<==> A2 + A3 #= 1,
 
% 8. If statement 7 is true, then 5 and 6 are both true.
A8 #<==> (A7 #==> A5 #/\ A6),
 
 
% 9. Exactly 3 of the first 6 statements are true.
A9 #<==> A1 + A2 + A3 + A4 + A5 + A6 #= 3,
 
% 10. The next two statements are both true.
A10 #<==> A11 #/\ A12,
 
% 11. Exactly 1 of statements 7, 8 and 9 are true.
A11 #<==> A7 + A8 + A9 #= 1,
 
% 12. Exactly 4 of the preceding statements are true.
A12 #<==> A1 + A2 + A3 + A4 + A5 + A6 + A7 +A8 + A9 + A10 + A11 #= 4,
 
label(L),
numlist(1, 12, NL),
write('Statements '),
maplist(my_write, NL, L),
writeln('are true').
 
 
my_write(N, 1) :-
format('~w ', [N]).
 
my_write(_N, 0).
 

Output :

 ?- puzzle.
Statements 1 3 4 6 7 11 are true
true .

[edit] Python

Note: we choose to adapt the statement numbering to zero-based indexing in the constraintinfo lambda expressions but convert back to one-based on output.

The program uses brute force to generate all possible boolean values of the twelve statements then checks if the actual value of the statements matches the proposed or matches apart from exactly one deviation. Python's boolean type boolis a subclass of int, so boolean values True, False can be used as integers (1, 0, respectively) in numerical contexts. This fact is used in the lambda expressions that use function sum.

 
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('Full match:')
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 stm in full + partial:
printer(*stm)
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

[edit] Racket

This question really begs to be done with amb

 
#lang racket
 
;; A quick `amb' implementation
(define failures null)
(define (fail)
(if (pair? failures) ((first failures)) (error "no more choices!")))
(define (amb/thunks choices)
(let/cc k (set! failures (cons k failures)))
(if (pair? choices)
(let ([choice (first choices)]) (set! choices (rest choices)) (choice))
(begin (set! failures (rest failures)) (fail))))
(define-syntax-rule (amb E ...) (amb/thunks (list (lambda () E) ...)))
(define (assert condition) (unless condition (fail)))
 
;; just to make things more fun
(define (⇔ x y) (assert (eq? x y)))
(require (only-in racket [and ∧] [or ∨] [implies ⇒] [xor ⊻] [not ¬]))
(define (count xs)
(let loop ([n 0] [xs xs])
(if (null? xs) n (loop (if (car xs) (add1 n) n) (cdr xs)))))
;; even more fun, make []s infix
(require (only-in racket [#%app r:app]))
(define-syntax (#%app stx)
(if (not (eq? #\[ (syntax-property stx 'paren-shape)))
(syntax-case stx () [(_ x ...) #'(r:app x ...)])
(syntax-case stx ()
 ;; extreme hack on next two cases, so it works for macros too.
[(_ x op y) (syntax-property #'(op x y) 'paren-shape #f)]
[(_ x op y op1 z) (free-identifier=? #'op #'op1)
(syntax-property #'(op x y z) 'paren-shape #f)])))
;; might as well do more
(define-syntax-rule (define-booleans all x ...)
(begin (define x (amb #t #f)) ...
(define all (list x ...))))
 
(define (puzzle)
(define-booleans all q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12)
 ;; 1. This is a numbered list of twelve statements.
[q1 ⇔ [12 = (length all)]]
 ;; 2. Exactly 3 of the last 6 statements are true.
[q2 ⇔ [3 = (count (take-right all 6))]]
 ;; 3. Exactly 2 of the even-numbered statements are true.
[q3 ⇔ [2 = (count (list q2 q4 q6 q8 q10 q12))]]
 ;; 4. If statement 5 is true, then statements 6 and 7 are both true.
[q4 ⇔ [q5 ⇒ [q6 ∧ q7]]]
 ;; 5. The 3 preceding statements are all false.
[q5 ⇔ (¬ [q2 ∨ q3 ∨ q4])]
 ;; 6. Exactly 4 of the odd-numbered statements are true.
[q6 ⇔ [4 = (count (list q1 q3 q5 q7 q9 q11))]]
 ;; 7. Either statement 2 or 3 is true, but not both.
[q7 ⇔ [q2 ⊻ q3]]
 ;; 8. If statement 7 is true, then 5 and 6 are both true.
[q8 ⇔ [q7 ⇒ (and q5 q6)]]
 ;; 9. Exactly 3 of the first 6 statements are true.
[q9 ⇔ [3 = (count (take all 3))]]
 ;; 10. The next two statements are both true.
[q10 ⇔ [q11 ∧ q12]]
 ;; 11. Exactly 1 of statements 7, 8 and 9 are true.
[q11 ⇔ [1 = (count (list q7 q8 q9))]]
 ;; 12. Exactly 4 of the preceding statements are true.
[q12 ⇔ [4 = (count (drop-right all 1))]]
 ;; done
(for/list ([i (in-naturals 1)] [q all] #:when q) i))
 
(puzzle)
;; -> '(1 3 4 6 7 11)
 
 

[edit] REXX

[edit] generalized logic

/*REXX program solves the  "Twelve Statement Puzzle".                   */
q=12; @stmt=right('statement',20) /*number of statements in puzzle.*/
m=0 /*[↓] statement 1 is TRUE by fiat*/
do pass=1 for 2 /*find the maximum number trues. */
do e=0 for 2**(q-1); n = '1'right(x2b(d2x(e)), q-1, 0)
do b=1 for q /*define the various bits. */
@.b=substr(n,b,1) /*define a particular @ bit. */
end /*b*/
if @.1 then if yeses(1,1) \==1 then iterate
if @.2 then if yeses(7,12) \==3 then iterate
if @.3 then if yeses(2,12,2) \==2 then iterate
if @.4 then if yeses(5,5) then if yeses(6,7) \==2 then iterate
if @.5 then if yeses(2,4) \==0 then iterate
if @.6 then if yeses(1,12,2) \==4 then iterate
if @.7 then if yeses(2,3) \==1 then iterate
if @.8 then if yeses(7,7) then if yeses(5,6) \==2 then iterate
if @.9 then if yeses(1,6) \==3 then iterate
if @.10 then if yeses(11,12) \==2 then iterate
if @.11 then if yeses(7,9) \==1 then iterate
if @.12 then if yeses(1,11) \==4 then iterate
_=yeses(1,12)
if pass==1 then do; m=max(m,_); iterate; end
else if _\==m then iterate
do j=1 for q; _=substr(n,j,1)
if _ then say @stmt right(j,2) " is " word('false true',1+_)
end /*tell*/
end /*e*/
end /*pass*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────YESES subroutine────────────────────*/
yeses: parse arg L,H,B; #=0; do i=L to H by word(B 1,1); #=#+@.i; end
return #

output

           statement  1  is  true
           statement  3  is  true
           statement  4  is  true
           statement  6  is  true
           statement  7  is  true
           statement 11  is  true

[edit] discrete logic

/*REXX program solves the  "Twelve Statement Puzzle".                   */
q=12; @stmt=right('statement',20) /*number of statements in puzzle.*/
m=0 /*[↓] statement 1 is TRUE by fiat*/
do pass=1 for 2 /*find the maximum number trues. */
do e=0 for 2**(q-1); n = '1'right(x2b(d2x(e)), q-1, 0)
do b=1 for q /*define the various bits. */
@.b=substr(n,b,1) /*define a particular @ bit. */
end /*b*/
if @.1 then if \ @.1 then iterate
if @.2 then if @.7+@.8+@.9+@.10+@.11+@.12 \==3 then iterate
if @.3 then if @.2+@.4+@.6+@.8+@.10+@.12 \==2 then iterate
if @.4 then if @.5 then if \(@.6 & @.7) then iterate
if @.5 then if @.2 | @.3 | @.4 then iterate
if @.6 then if @.1+@.3+@.5+@.7+@.9+@.11 \==4 then iterate
if @.7 then if \ (@.2 && @.3 ) then iterate
if @.8 then if @.7 then if \(@.5 & @.6) then iterate
if @.9 then if @.1+@.2+@.3+@.4+@.5+@.6 \==3 then iterate
if @.10 then if \ (@.11 & @.12) then iterate
if @.11 then if @.7+@.8+@.9 \==1 then iterate
_=@.1+@.2+@.3+@.4+@.5+@.6+@.7+@.8+@.9+@.10+@.11
if @.12 then if _ \==4 then iterate
_=_+@.12
if pass==1 then do; m=max(m,_); iterate; end
else if _\==m then iterate
do j=1 for q
if @.j then say @stmt right(j,2) " is " word('false true',1+@.j)
end /*j*/
end /*e*/
end /*pass*/
/*stick a fork in it, we're done.*/

output is the same as the 1st version.

[edit] optimized

/*REXX program solves the  "Twelve Statement Puzzle".                   */
q=12; @stmt=right('statement',20) /*number of statements in puzzle.*/
m=0 /*[↓] statement 1 is TRUE by fiat*/
do pass=1 for 2 /*find the maximum number trues. */
do e=0 for 2**(q-1); n = '1'right(x2b(d2x(e)), q-1, 0)
parse var n @1 2 @2 3 @3 4 @4 5 @5 6 @6 7 @7 8 @8 9 @9 10 @10 11 @11 12 @12
/*███ if @1 then if \ @1 then iterate ███*/
if @2 then if @7+@8+@9+@10+@11+@12 \==3 then iterate
if @3 then if @2+@4+@6+@8+@10+@12 \==2 then iterate
if @4 then if @5 then if \(@6 & @7) then iterate
if @5 then if @2 | @3 | @4 then iterate
if @6 then if @1+@3+@5+@7+@9+@11 \==4 then iterate
if @7 then if \ (@2 && @3 ) then iterate
if @8 then if @7 then if \(@5 & @6) then iterate
if @9 then if @1+@2+@3+@4+@5+@6 \==3 then iterate
if @10 then if \ (@11 & @12) then iterate
if @11 then if @7+@8+@9 \==1 then iterate
_=@1+@2+@3+@4+@5+@6+@7+@8+@9+@10+@11 /*shortcut*/
if @12 then if _ \==4 then iterate
_=_+@12
if pass==1 then do; m=max(m,_); iterate; end
else if _\==m then iterate
do j=1 for q; _=substr(n,j,1)
if _ then say @stmt right(j,2) " is " word('false true',1+_)
end /*j*/
end /*e*/
end /*pass*/
/*stick a fork in it, we're done.*/

output is the same as the 1st version.

[edit] Ruby

constraints = [
->(st) { st.size == 12 },
->(st) { st[-6,6].count(true) == 3 },
->(st) { st.each_slice(2).map(&:last).count(true) == 2 },
->(st) { st[4] ? (st[5] & st[6]) : true },
->(st) { st[1..3].map(&:!).all? },
->(st) { st.each_slice(2).map(&:first).count(true) == 4 },
->(st) { st[1] ^ st[2] },
->(st) { st[6] ? (st[4] & st[5]) : true },
->(st) { st[0,6].count(true) == 3 },
->(st) { st[10] & st[11] },
->(st) { st[6..8].count(true) == 1 },
->(st) { st[0,11].count(true) == 4 },
]
 
Result = Struct.new(:truths, :consistency)
 
results = [true, false].repeated_permutation(12).map do |truths|
Result.new(truths, constraints.zip(truths).map {|cn,truth| cn[truths] == truth })
end
 
puts "solution:",
results.find {|r| r.consistency.all? }.truths.inspect
 
puts "near misses: "
near_misses = results.select {|r| r.consistency.count(false) == 1 }
near_misses.each do |r|
puts "missed by statement #{r.consistency.index(false) + 1}"
puts r.truths.inspect
end
Output:
solution:
[true, false, true, true, false, true, true, false, false, false, true, false]
near misses: 
missed by statement 8
[true, true, false, true, false, false, true, true, true, false, false, false]
missed by statement 10
[true, true, false, true, false, false, true, false, true, true, false, false]
missed by statement 12
[true, true, false, true, false, false, true, false, true, false, false, true]
missed by statement 9
[true, false, true, true, false, true, true, false, true, false, false, false]
missed by statement 7
[true, false, true, true, false, false, false, true, true, false, false, false]
missed by statement 6
[true, false, false, true, false, true, false, true, true, false, false, false]
missed by statement 12
[true, false, false, true, false, false, false, true, false, true, true, true]
missed by statement 8
[true, false, false, true, false, false, false, false, false, false, false, false]
missed by statement 8
[true, false, false, false, true, true, false, false, true, false, true, false]
missed by statement 12
[true, false, false, false, true, false, false, true, false, true, true, true]
missed by statement 12
[true, false, false, false, true, false, false, true, false, false, true, false]
missed by statement 11
[true, false, false, false, true, false, false, true, false, false, false, false]
missed by statement 8
[true, false, false, false, true, false, false, false, false, false, false, false]
missed by statement 1
[false, false, false, true, false, false, false, true, false, true, true, true]
missed by statement 1
[false, false, false, false, true, false, false, true, false, true, true, true]
missed by statement 1
[false, false, false, false, true, false, false, true, false, false, true, false]

[edit] Tcl

Works with: Tcl version 8.6
package require Tcl 8.6
 
# Function to evaluate the truth of a statement
proc tcl::mathfunc::S {idx} {
upvar 1 state s
apply [lindex $s [expr {$idx - 1}]] $s
}
# Procedure to count the number of statements which are true
proc S+ args {
upvar 1 state state
tcl::mathop::+ {*}[lmap i $args {expr {S($i)}}]
}
# Turn a list of expressions into a list of lambda terms
proc lambdas items {lmap x $items {list state [list expr $x]}}
 
# Find the truth assignment that produces consistency. And those that are
# near misses too.
proc findTruthMatch {statements} {
set n [llength $statements]
for {set i 0} {$i < 2**$n} {incr i} {
set state [split [format %0.*b $n $i] ""]
set truths [lmap f $statements {apply $f [lambdas $state]}]
set counteq [tcl::mathop::+ {*}[lmap s $state t $truths {expr {
$s == $t
}}]]
if {$counteq == $n} {
lappend exact $state
} elseif {$counteq == $n-1} {
set j 0
foreach s $state t $truths {
incr j
if {$s != $t} {
lappend differ $state $j
break
}
}
}
}
return [list $exact $differ]
}
 
# Rendering code
proc renderstate state {
return ([join [lmap s $state {
incr i
expr {$s ? "S($i)" : "\u00acS($i)"}
}] "\u22c0"])
}
 
# The statements, encoded as expressions
set statements {
{[llength $state] == 12}
{[S+ 7 8 9 10 11 12] == 3}
{[S+ 2 4 6 8 10 12] == 2}
{S(5) ? S(6) && S(7) : 1}
{[S+ 2 3 4] == 0}
{[S+ 1 3 5 7 9 11] == 4}
{S(2) != S(3)}
{S(7) ? S(5) && S(6) : 1}
{[S+ 1 2 3 4 5 6] == 3}
{S(11) && S(12)}
{[S+ 7 8 9] == 1}
{[S+ 1 2 3 4 5 6 7 8 9 10 11] == 4}
}
# Find the truth assignment(s) that give consistency
lassign [findTruthMatch [lambdas $statements]] exact differ
# Print the results
foreach state $exact {
puts "exact match\t[renderstate $state ]"
}
foreach {state j} $differ {
puts "almost found\t[renderstate $state] \u21d2 [expr {[lindex $state $j-1]?"\u00ac":{}}]S($j)"
}
Output:
exact match     (S(1)?¬S(2)?S(3)?S(4)?¬S(5)?S(6)?S(7)?¬S(8)?¬S(9)?¬S(10)?S(11)?¬S(12))
almost found    (¬S(1)?¬S(2)?¬S(3)?¬S(4)?S(5)?¬S(6)?¬S(7)?S(8)?¬S(9)?¬S(10)?S(11)?¬S(12)) ? S(1)
almost found    (¬S(1)?¬S(2)?¬S(3)?¬S(4)?S(5)?¬S(6)?¬S(7)?S(8)?¬S(9)?S(10)?S(11)?S(12)) ? S(1)
almost found    (¬S(1)?¬S(2)?¬S(3)?S(4)?¬S(5)?¬S(6)?¬S(7)?S(8)?¬S(9)?S(10)?S(11)?S(12)) ? S(1)
almost found    (S(1)?¬S(2)?¬S(3)?¬S(4)?S(5)?¬S(6)?¬S(7)?¬S(8)?¬S(9)?¬S(10)?¬S(11)?¬S(12)) ? S(8)
almost found    (S(1)?¬S(2)?¬S(3)?¬S(4)?S(5)?¬S(6)?¬S(7)?S(8)?¬S(9)?¬S(10)?¬S(11)?¬S(12)) ? S(11)
almost found    (S(1)?¬S(2)?¬S(3)?¬S(4)?S(5)?¬S(6)?¬S(7)?S(8)?¬S(9)?¬S(10)?S(11)?¬S(12)) ? S(12)
almost found    (S(1)?¬S(2)?¬S(3)?¬S(4)?S(5)?¬S(6)?¬S(7)?S(8)?¬S(9)?S(10)?S(11)?S(12)) ? ¬S(12)
almost found    (S(1)?¬S(2)?¬S(3)?¬S(4)?S(5)?S(6)?¬S(7)?¬S(8)?S(9)?¬S(10)?S(11)?¬S(12)) ? S(8)
almost found    (S(1)?¬S(2)?¬S(3)?S(4)?¬S(5)?¬S(6)?¬S(7)?¬S(8)?¬S(9)?¬S(10)?¬S(11)?¬S(12)) ? S(8)
almost found    (S(1)?¬S(2)?¬S(3)?S(4)?¬S(5)?¬S(6)?¬S(7)?S(8)?¬S(9)?S(10)?S(11)?S(12)) ? ¬S(12)
almost found    (S(1)?¬S(2)?¬S(3)?S(4)?¬S(5)?S(6)?¬S(7)?S(8)?S(9)?¬S(10)?¬S(11)?¬S(12)) ? ¬S(6)
almost found    (S(1)?¬S(2)?S(3)?S(4)?¬S(5)?¬S(6)?¬S(7)?S(8)?S(9)?¬S(10)?¬S(11)?¬S(12)) ? S(7)
almost found    (S(1)?¬S(2)?S(3)?S(4)?¬S(5)?S(6)?S(7)?¬S(8)?S(9)?¬S(10)?¬S(11)?¬S(12)) ? ¬S(9)
almost found    (S(1)?S(2)?¬S(3)?S(4)?¬S(5)?¬S(6)?S(7)?¬S(8)?S(9)?¬S(10)?¬S(11)?S(12)) ? ¬S(12)
almost found    (S(1)?S(2)?¬S(3)?S(4)?¬S(5)?¬S(6)?S(7)?¬S(8)?S(9)?S(10)?¬S(11)?¬S(12)) ? ¬S(10)
almost found    (S(1)?S(2)?¬S(3)?S(4)?¬S(5)?¬S(6)?S(7)?S(8)?S(9)?¬S(10)?¬S(11)?¬S(12)) ? ¬S(8)

[edit] TXR

@(do
(defmacro defconstraints (name size-name (var) . forms)
^(progn (defvar ,size-name ,(length forms))
(defun ,name (,var)
(list ,*forms))))
 
(defconstraints con con-count (s)
(= (length s) con-count) ;; tautology
(= (countq t [s -6..t]) 3)
(= (countq t (mapcar (op if (evenp @1) @2) (range 1) s)) 2)
(if [s 4] (and [s 5] [s 6]) t)
(none [s 1..3])
(= (countq t (mapcar (op if (oddp @1) @2) (range 1) s)) 4)
(and (or [s 1] [s 2]) (not (and [s 1] [s 2])))
(if [s 6] (and [s 4] [s 5]) t)
(= (countq t [s 0..6]) 3)
(and [s 10] [s 11])
(= (countq t [s 6..9]) 1)
(= (countq t [s 0..con-count]) 4))
 
(defun true-indices (truths)
(mappend (do if @1 ^(,@2)) truths (range 1)))
 
(defvar results
(append-each ((truths (rperm '(nil t) con-count)))
(let* ((vals (con truths))
(consist [mapcar eq truths vals])
(wrong-count (countq nil consist))
(pos-wrong (+ 1 (or (posq nil consist) -2))))
(cond
((zerop wrong-count)
^((:----> ,*(true-indices truths))))
((= 1 wrong-count)
^((:close ,*(true-indices truths) (:wrong ,pos-wrong))))))))
 
(each ((r results))
(put-line `@r`)))

Output:

close 5 8 11 (wrong 1)
close 1 5 (wrong 8)
close 1 5 8 (wrong 11)
close 1 5 8 11 (wrong 12)
close 1 5 8 10 11 12 (wrong 12)
close 1 5 6 9 11 (wrong 8)
close 1 3 4 8 9 (wrong 7)
----> 1 3 4 6 7 11
close 1 3 4 6 7 9 (wrong 9)
close 1 2 4 7 9 12 (wrong 12)
close 1 2 4 7 9 10 (wrong 10)
close 1 2 4 7 8 9 (wrong 8)
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox