on master help sign in
Initial commit
commit60666aee5628e1a764768dd1d97e680176bd3877 authorilyakooo0 <ilyakooo0@gmail.com> dateSat 7 Oct 2017, 17:11 (9 years ago) parentacc981e
7 files changed+340−2
Truther.xcodeproj/project.pbxproj+14 Truther.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist+8 Truther/Formatter.swift+39 Truther/Operator.swift+94 Truther/README.md+36 Truther/Truther.swift+140 Truther/main.swift+9−2
Truther.xcodeproj/project.pbxproj+14
@@ -7,7 +7,10 @@
77 objects = {
88
99/* Begin PBXBuildFile section */
10+ 091685E31F8834C800CC8645 /* Formatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 091685E21F8834C800CC8645 /* Formatter.swift */; };
1011 097824FA1F87E21400064ADB /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097824F91F87E21400064ADB /* main.swift */; };
12+ 097825011F87E23000064ADB /* Truther.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097825001F87E23000064ADB /* Truther.swift */; };
13+ 097825031F87E48500064ADB /* Operator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097825021F87E48500064ADB /* Operator.swift */; };
1114/* End PBXBuildFile section */
1215
1316/* Begin PBXCopyFilesBuildPhase section */
@@ -23,8 +26,12 @@
2326/* End PBXCopyFilesBuildPhase section */
2427
2528/* Begin PBXFileReference section */
29+ 0915F8131F8907DB00D96279 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
30+ 091685E21F8834C800CC8645 /* Formatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Formatter.swift; sourceTree = "<group>"; };
2631 097824F61F87E21400064ADB /* Truther */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Truther; sourceTree = BUILT_PRODUCTS_DIR; };
2732 097824F91F87E21400064ADB /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
33+ 097825001F87E23000064ADB /* Truther.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Truther.swift; sourceTree = "<group>"; };
34+ 097825021F87E48500064ADB /* Operator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Operator.swift; sourceTree = "<group>"; };
2835/* End PBXFileReference section */
2936
3037/* Begin PBXFrameworksBuildPhase section */
@@ -58,6 +65,10 @@
5865 isa = PBXGroup;
5966 children = (
6067 097824F91F87E21400064ADB /* main.swift */,
68+ 097825001F87E23000064ADB /* Truther.swift */,
69+ 0915F8131F8907DB00D96279 /* README.md */,
70+ 091685E21F8834C800CC8645 /* Formatter.swift */,
71+ 097825021F87E48500064ADB /* Operator.swift */,
6172 );
6273 path = Truther;
6374 sourceTree = "<group>";
@@ -120,6 +131,9 @@
120131 isa = PBXSourcesBuildPhase;
121132 buildActionMask = 2147483647;
122133 files = (
134+ 097825011F87E23000064ADB /* Truther.swift in Sources */,
135+ 097825031F87E48500064ADB /* Operator.swift in Sources */,
136+ 091685E31F8834C800CC8645 /* Formatter.swift in Sources */,
123137 097824FA1F87E21400064ADB /* main.swift in Sources */,
124138 );
125139 runOnlyForDeploymentPostprocessing = 0;
Truther.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist+8
@@ -10,5 +10,13 @@
1010 <integer>0</integer>
1111 </dict>
1212 </dict>
13+ <key>SuppressBuildableAutocreation</key>
14+ <dict>
15+ <key>097824F51F87E21400064ADB</key>
16+ <dict>
17+ <key>primary</key>
18+ <true/>
19+ </dict>
20+ </dict>
1321</dict>
1422</plist>
Truther/Formatter.swiftnew file+39
@@ -0,0 +1,39 @@
1+//
2+// Formatter.swift
3+// Truther
4+//
5+// Created by Ilya Kos on 10/7/17.
6+// Copyright © 2017 Ilya Kos. All rights reserved.
7+//
8+
9+import Foundation
10+
11+private let seperator = " | "
12+
13+class Formatter {
14+ static func format(table: [[String]]) -> String {
15+ var lengths: [Int] = []
16+ for i in 0..<table[0].count {
17+ var maxLength = 0
18+ for row in table {
19+ maxLength = max(maxLength, row[i].count)
20+ }
21+ lengths.append(maxLength)
22+ }
23+ var out = ""
24+ for i in 0..<table.count {
25+ let row = table[i]
26+ for u in 0..<row.count {
27+ out.append(row[u].padding(toLength: lengths[u], withPad: " ", startingAt: 0))
28+ out.append(seperator)
29+ }
30+ out = String(out.dropLast(seperator.count))
31+ out.append("\n")
32+ if i == 0 {
33+ out.append(String.init(repeating: "-", count: lengths.reduce(0, +) + seperator.count * (lengths.count - 1)))
34+ out.append("\n")
35+ }
36+ }
37+ return out
38+ }
39+}
Truther/Operator.swiftnew file+94
@@ -0,0 +1,94 @@
1+//
2+// Operator.swift
3+// Truther
4+//
5+// Created by Ilya Kos on 10/6/17.
6+// Copyright © 2017 Ilya Kos. All rights reserved.
7+//
8+
9+import Foundation
10+
11+enum Operator {
12+ case f0
13+ case f1
14+ case f2
15+ case f3
16+ case f4
17+ case f5
18+ case f6
19+ case f7
20+ case f8
21+ case f9
22+ case f10
23+ case f11
24+ case f12
25+ case f13
26+ case f14
27+ case f15
28+ var value: ((Bool, Bool) -> (Bool)) {
29+ switch self {
30+ case .f0:
31+ return {_, _ in false}
32+ case .f1:
33+ return {$0 && $1}
34+ case .f2:
35+ return { $0 && !$1 }
36+ case .f3:
37+ return {a, _ in a}
38+ case .f4:
39+ return {!$0 && $1}
40+ case .f5:
41+ return {_, b in b }
42+ case .f6:
43+ return {!($0 == $1)}
44+ case .f7:
45+ return {$0 || $1}
46+ case .f8:
47+ return {!($0 && $1)}
48+ case .f9:
49+ return {$0 == $1}
50+ case .f10:
51+ return {_, b in !b}
52+ case .f11:
53+ return {!(!$0 && $1)}
54+ case .f12:
55+ return {a, _ in !a}
56+ case .f13:
57+ return {!($0 && !$1)}
58+ case .f14:
59+ return {!($0 && $1)}
60+ case .f15:
61+ return {_, _ in true}
62+ }
63+ }
64+ static func process(_ op: Substring) -> Operator? {
65+ switch op.trimmingCharacters(in: .whitespaces).lowercased() {
66+ case "+", "or", "||":
67+ return .f7
68+ case "(+)", "⊕", "xor", "!=", "=!=", "=/=", "/=":
69+ return .f6
70+ case "*", "and", "&", "&&", "⚫︎":
71+ return .f1
72+ case "1":
73+ return .f15
74+ case "0":
75+ return .f0
76+ case "=/>", "=/=>", "-/>", "-/->", "!=>", "!->", "=!>", "-!>", "=!=>", "-!->":
77+ return .f2
78+ case "</=", "<=/=", "</-", "<-/-", "!<=", "!<-", "<!=", "<!-", "<=!=", "<-!-":
79+ return .f4
80+ case "o", "O", "о", "О", "◯", "⚬", "𐩒", "⚪︎", "nor", "web":
81+ return .f8
82+ case "=", "<=>", "==":
83+ return .f9
84+ case "<=", "<-", "<==", "<--":
85+ return .f11
86+ case "=>", "->", "==>", "-->":
87+ return .f13
88+ case "|", "nand", "shif":
89+ return .f14
90+ default:
91+ return nil
92+ }
93+ }
94+}
Truther/README.mdnew file+36
@@ -0,0 +1,36 @@
1+# Truther
2+
3+Makes a truth table for the given boolean function
4+
5+
6+## Usage
7+
8+```
9+truther "a * c (+) b"
10+```
11+
12+```
13+a | b | c | F
14+-------------
15+0 | 0 | 0 | 0
16+0 | 0 | 1 | 0
17+0 | 1 | 0 | 1
18+0 | 1 | 1 | 1
19+1 | 0 | 0 | 0
20+1 | 0 | 1 | 1
21+1 | 1 | 0 | 1
22+1 | 1 | 1 | 0
23+```
24+
25+## Available functions
26+
27+- `+`/`or`
28+- `(+)`/`xor`/`/=`
29+- `*`/`and`/`&`
30+- `=>`
31+- `=/>`
32+- `<=`
33+- `</=`
34+- `o`/`nor`
35+- `=`/`<=>`
36+- `|`/`nand`
Truther/Truther.swiftnew file+140
@@ -0,0 +1,140 @@
1+//
2+// Truther.swift
3+// Truther
4+//
5+// Created by Ilya Kos on 10/6/17.
6+// Copyright © 2017 Ilya Kos. All rights reserved.
7+//
8+
9+import Foundation
10+
11+struct Truther {
12+ var formula: Formula
13+ func run() -> [(inp: [Bool], result: Bool)] {
14+ var out: [(inp: [Bool], result: Bool)] = []
15+ for i in 0..<Int(pow(2, Double(formula.variables.count))) {
16+ var t = 0
17+ var inp: [Bool] = []
18+ for _ in formula.variables {
19+ inp.append((UInt(i)>>t) & 1 == 1)
20+ t += 1
21+ }
22+ inp = inp.reversed()
23+ out.append((inp, formula.run(with: inp)))
24+ }
25+ return out
26+ }
27+}
28+
29+struct Formula {
30+ fileprivate func run(with inputs: [Bool]) -> Bool {
31+ var ins: [Variable: Bool] = [:]
32+ for (v, va) in zip(variables, inputs) {
33+ ins[v] = va
34+ }
35+ return value.evaluate(with: ins)
36+ }
37+ init(_ f: String) {
38+ var vars: Set<String> = Set()
39+ func process(_ s: Substring, startingLeft: FormulaElement? = nil) -> FormulaElement {
40+ if s.isEmpty {
41+ guard let startingLeft = startingLeft else {
42+ print("Internal error: Empty input")
43+ exit(1)
44+ }
45+ return startingLeft
46+ }
47+ var ns = s.trimmingCharacters(in: .whitespaces)
48+ if ns.trimmingCharacters(in: .whitespaces).reduce(true, {$0 && CharacterSet.letters.contains($1.unicodeScalars.first!)}) {
49+ vars.insert(String(s))
50+ return .variable(String(s))
51+ }
52+ func extractVar() -> Substring {
53+ if ns.first == "(" {
54+ let parts = extractBrackets(from: ns)
55+ ns = parts.after.trimmingCharacters(in: .whitespaces)
56+ return Substring(parts.wasInside.trimmingCharacters(in: .whitespaces))
57+ } else {
58+ if CharacterSet.whitespaces.contains((ns.first?.unicodeScalars.first)!) {
59+ print("Internal error: weird variable name first charecter \(ns.first!)")
60+ exit(1)
61+ }
62+ var i = ns.startIndex
63+ while i < ns.endIndex {
64+ if !CharacterSet.letters.contains(ns[i].unicodeScalars.first!) {
65+ break
66+ }
67+ i = ns.index(after: i)
68+ }
69+ let out = ns[..<i]
70+ ns = ns[i...].trimmingCharacters(in: .whitespaces)
71+ return out
72+ }
73+ }
74+ let left = startingLeft ?? process(extractVar())
75+ ns = ns.trimmingCharacters(in: .whitespaces)
76+ let isLetterOrNot = CharacterSet.letters.contains((ns.first?.unicodeScalars.first)!)
77+ var i = ns.startIndex
78+ while i < ns.endIndex {
79+ if CharacterSet.letters.contains(ns[i].unicodeScalars.first!) != isLetterOrNot || ns[i] == " " {
80+ break
81+ }
82+ i = ns.index(after: i)
83+ }
84+ guard let op = Operator.process(ns[..<i]) else {
85+ print("No such operator \(ns[..<i])")
86+ exit(1)
87+ }
88+ ns = ns[i...].trimmingCharacters(in: .whitespaces)
89+ let right = process(extractVar())
90+ return process(Substring(ns), startingLeft: .operation(left, op, right))
91+ }
92+ self.value = process(Substring(f))
93+ self.variables = vars.sorted()
94+ }
95+ let variables: [String]
96+ private let value: FormulaElement
97+}
98+
99+private func extractBrackets(from s: String) -> (wasInside: Substring, after: Substring) {
100+ var i = s.startIndex
101+ var brackets = 0
102+ while i < s.endIndex {
103+ switch s[i] {
104+ case "(":
105+ brackets += 1
106+ case ")":
107+ brackets -= 1
108+ default:
109+ break
110+ }
111+ if brackets == 0 {
112+ break
113+ }
114+ i = s.index(after: i)
115+ }
116+ if brackets != 0 {
117+ print("Mismatched brackets")
118+ exit(1)
119+ }
120+ return (s[s.index(after: s.startIndex)..<i], s[s.index(after: i)...])
121+}
122+
123+private typealias Variable = String
124+private indirect enum FormulaElement {
125+ case variable(Variable)
126+ case operation(FormulaElement, Operator, FormulaElement)
127+ func evaluate(with variables: [Variable: Bool]) -> Bool {
128+ switch self {
129+ case .variable(let v):
130+ if let va = variables[v] {
131+ return va
132+ } else {
133+ print("Internal error: didn't initialize all variables")
134+ exit(1)
135+ }
136+ case .operation(let l, let op, let r):
137+ return op.value(l.evaluate(with: variables), r.evaluate(with: variables))
138+ }
139+ }
140+}
Truther/main.swift+9−2
@@ -8,5 +8,12 @@
88
99import Foundation
1010
11−print("Hello, World!")
12−
11+if CommandLine.arguments.count > 1 {
12+ let form = Formula.init(CommandLine.arguments[1])
13+ let table = Truther.init(formula: form).run().map { $0.0 + [$0.1] }
14+ .map {$0.map {$0 ? "1" : "0"}}
15+
16+ print(Formatter.format(table: [form.variables + ["F"]] + table))
17+} else {
18+ print("You did't supply a formula")
19+}