Task: Twelve statements




Go: package main

import "fmt"


var solution = make(chan int)
var nearMiss = make(chan int)
var done = make(chan bool)

func main() {
    
    for i := 0; i < 4096; i++ {
        go checkPerm(i)
    }
    
    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) {
    
    
    ts := func(n uint) bool {
        return tz>>(n-1)&1 == 1
    }
    
    
    ntrue := func(xs ...uint) int {
        nt := 0
        for _, x := range xs {
            if ts(x) {
                nt++
            }
        }
        return nt
    }
    
    
    
    
    var con bool
    
    test := func(statement uint, b bool) {
        switch {
        case ts(statement) == b:
        case con:
            panic("bail")
        default:
            con = true
        }
    }
    
    defer func() {
        if x := recover(); x != nil {
            if msg, ok := x.(string); !ok && msg != "bail" {
                panic(x)
            }
        }
        done <- true
    }()

    
    test(1, true)

    
    test(2, ntrue(7, 8, 9, 10, 11, 12) == 3)

    
    test(3, ntrue(2, 4, 6, 8, 10, 12) == 2)

    
    test(4, !ts(5) || ts(6) && ts(7))

    
    test(5, !ts(4) && !ts(3) && !ts(2))

    
    test(6, ntrue(1, 3, 5, 7, 9, 11) == 4)

    
    test(7, ts(2) != ts(3))

    
    test(8, !ts(7) || ts(5) && ts(6))

    
    test(9, ntrue(1, 2, 3, 4, 5, 6) == 3)
    
    
    test(10, ts(11) && ts(12))
    
    
    test(11, ntrue(7, 8, 9) == 1)
    
    
    test(12, ntrue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) == 4)

    
    if con {
        nearMiss <- tz
    } else {
        solution <- tz
    }
}








Ada: with Ada.Text_IO, Logic; 

procedure Twelve_Statements is
   
   package L is new Logic(Number_Of_Statements => 12); use L;
   
   
   function P01(T: Table) return Boolean is (T'Length = 12);              
   function P02(T: Table) return Boolean is (Sum(T(7 .. 12)) = 3);        
   function P03(T: Table) return Boolean is (Sum(Half(T, Even)) = 2);     
   function P04(T: Table) return Boolean is (if T(5) then T(6) and T(7)); 
   function P05(T: Table) return Boolean is 
      ( (not T(2)) and (not T(3)) and (not T(4)) );                       
   function P06(T: Table) return Boolean is (Sum(Half(T, Odd)) = 4);      
   function P07(T: Table) return Boolean is (T(2) xor T(3));              
   function P08(T: Table) return Boolean is (if T(7) then T(5) and T(6)); 
   function P09(T: Table) return Boolean is (Sum(T(1 .. 6)) = 3);         
   function P10(T: Table) return Boolean is (T(11) and T(12));            
   function P11(T: Table) return Boolean is (Sum(T(7..9)) = 1);           
   function P12(T: Table) return Boolean is (Sum(T(1 .. 11)) = 4);        
   
   
   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);
   
   
   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 
	 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;