This puzzle is borrowed from   math-frolic.blogspot.



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.



Task

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

Print out a table of near misses, that is, solutions that are contradicted by only a single statement.




import "/fmt" for Conv, Fmt
 
var predicates = [
    Fn.new { |s| s.count == 13 },  // indexing starts at 0 but first bit ignored
    Fn.new { |s| (7..12).count { |i| s[i] == "1" } == 3 },
    Fn.new { |s| [2, 4, 6, 8, 10, 12].count { |i| s[i] == "1" } == 2 },
    Fn.new { |s| s[5] == "0" || (s[6] == "1" && s[7] == "1") },
    Fn.new { |s| s[2] == "0" && s[3]  == "0" && s[4] == "0" },
    Fn.new { |s| [1, 3, 5, 7, 9, 11].count { |i| s[i] == "1" } == 4 },
    Fn.new { |s| Conv.itob(Conv.btoi(s[2] == "1") ^ Conv.btoi(s[3] == "1")) },
    Fn.new { |s| s[7] == "0" || (s[5] == "1" && s[6] == "1") },
    Fn.new { |s| (1..6).count { |i| s[i] == "1" } == 3 },
    Fn.new { |s| s[11] == "1" && s[12] == "1" },
    Fn.new { |s| (7..9).count { |i| s[i] == "1" } == 1 },
    Fn.new { |s| (1..11).count { |i| s[i] == "1" } == 4 }
]
 
var show = Fn.new { |s, indent|
    if (indent) System.write("    ")
    for (i in 0...s.count) if (s[i] == "1") System.write("%(i) ")
    System.print()
}
 
System.print("Exact hits:")
for (i in 0..4095) {
    var s = Fmt.swrite("$013b", i)
    var j = 1
    if (predicates.all { |pred|
       var res = pred.call(s) == (s[j] == "1")
       j = j + 1
       return res
    }) show.call(s, true)
}
 
System.print("\nNear misses:")
for (i in 0..4095) {
    var s = Fmt.swrite("$013b", i)
    var j = 1
    var c = predicates.count { |pred|
        var res = pred.call(s) == (s[j] == "1") 
        j = j + 1
        return res
    }
    if (c == 11) {
        var k = 1
        for (pred in predicates) {
            if (pred.call(s) != (s[k] == "1") ) break
            k = k + 1
        }
        Fmt.write("    (Fails at statement $2d)  ", k)
        show.call(s, false)
    }
}