all tasks

This commit is contained in:
Ingy döt Net 2013-04-11 01:07:29 -07:00
parent b83f433714
commit 68f8f3e56b
14735 changed files with 178959 additions and 0 deletions

View file

@ -0,0 +1,20 @@
This puzzle is borrowed from [http://math-frolic.blogspot.co.uk/2012/08/mind-wrenching.html here].
Given the following twelve statements, which of them are true?
<pre>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.</pre>
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.

View file

@ -0,0 +1,79 @@
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;

View file

@ -0,0 +1,16 @@
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;

View file

@ -0,0 +1,27 @@
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;

View file

@ -0,0 +1,43 @@
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

View file

@ -0,0 +1,63 @@
import std.stdio, std.typecons, 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"];
alias curry!(reduce!q{a + b}, 0) sumi;
immutable bool function(in bool[])[] funcs = [
s => s.length == 12,
s => sumi(s[$-6 .. $]) == 3,
s => sumi(s[1 .. $].stride(2)) == 2,
s => s[4] ? (s[5] && s[6]) : true,
s => sumi(s[1 .. 4]) == 0,
s => sumi(s[0 .. $].stride(2)) == 4,
s => sumi(s[1 .. 3]) == 1,
s => s[6] ? (s[4] && s[5]) : true,
s => sumi(s[0 .. 6]) == 3,
s => s[10] && s[11],
s => sumi(s[6 .. 9]) == 1,
s => sumi(s[0 .. 11]) == 4];
void main() {
enum nStats = 12;
Tuple!(const bool[], const bool[])[] full, partial;
foreach (n; 0 .. 2 ^^ nStats) {
const st = iota(nStats).map!(i => !!(n & (2 ^^ i)))().array();
auto truths = funcs.map!(f => f(st))();
const matches = zip(st, truths)
.map!(s_t => s_t[0] == s_t[1])()
.array();
immutable mCount = matches.sumi();
if (mCount == nStats)
full ~= tuple(st, matches);
else if (mCount == nStats - 1)
partial ~= tuple(st, matches);
}
foreach (sols, isPartial; zip([full, partial], [false, true]))
foreach (stm; sols) {
if (isPartial) {
immutable pos = stm[1].countUntil(false);
writefln(`Missed by statement %d: "%s"`,
pos + 1, texts[pos]);
} else
writeln("Solution:");
write(" ");
foreach (i, t; stm[0])
writef("%d:%s ", i + 1, t ? "T" : "F");
writeln();
}
}

View file

@ -0,0 +1,127 @@
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
}
}

View file

@ -0,0 +1,55 @@
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()

View file

@ -0,0 +1,29 @@
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

View file

@ -0,0 +1,6 @@
apply
128!:2
NB. example
'*:' apply 1 2 3
1 4 9

View file

@ -0,0 +1,16 @@
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&^)@#

View file

@ -0,0 +1,4 @@
(#~0=#@{::~&_1"1) testall S
+------------------------+
¦1 0 1 1 0 1 1 0 0 0 1 0¦¦
+------------------------+

View file

@ -0,0 +1,34 @@
(#~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 ¦
+--------------------------+

View file

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

View file

@ -0,0 +1,113 @@
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.");
}
}

View file

@ -0,0 +1,10 @@
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]]

View file

@ -0,0 +1,42 @@
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;

View file

@ -0,0 +1,51 @@
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).

View file

@ -0,0 +1,40 @@
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)

View file

@ -0,0 +1,37 @@
/*REXX program to solve the "Twelve Statement Puzzle". */
q=12; @stmt=right('statement',20) /*number of statements in puzzle.*/
m=0
do pass=1 for 2 /*find the maximum number trues. */
/*statement 1 is TRUE by fiat. */
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 /*i*/
return #

View file

@ -0,0 +1,34 @@
/*REXX program to solve the "Twelve Statement Puzzle". */
q=12; @stmt=right('statement',20) /*number of statements in puzzle.*/
m=0
do pass=1 for 2 /*find the maximum number trues. */
/*statement 1 is TRUE by fiat. */
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.*/

View file

@ -0,0 +1,30 @@
/*REXX program to solve the "Twelve Statement Puzzle". */
q=12; @stmt=right('statement',20) /*number of statements in puzzle.*/
m=0
do pass=1 for 2 /*find the maximum number trues. */
/*statement 1 is TRUE by fiat. */
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.*/

View file

@ -0,0 +1,30 @@
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

View file

@ -0,0 +1,73 @@
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)"
}