logicle 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ # emacs
2
+ *~
3
+ \#*\#
4
+
5
+ # Ruby / Rubygems
6
+ *.gem
7
+
8
+ # Bundler
9
+ .bundle
10
+ vendor/bundle
11
+
12
+ # Misc
13
+ *.gml
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org/"
2
+
3
+ gemspec
@@ -0,0 +1,8 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+
5
+ PLATFORMS
6
+ ruby
7
+
8
+ DEPENDENCIES
@@ -0,0 +1,43 @@
1
+ # Academic Exercise: Digital Logic Simulator
2
+
3
+ _written by Gregory Brown for Mendicant University core skills session #9_
4
+
5
+ I had a lot of fun coming up with the ["All Wired Up" PuzzleNode problem](http://puzzlenode.com/puzzles/18)
6
+ that was part of this session's entrance
7
+ exam. At the time I was writing it, I had thought about building a more
8
+ generally useful tool for playing around with simulated digital circuits,
9
+ but then I quickly got too busy to look into it further.
10
+
11
+ Then, I started playing Minecraft and my interest in circuitry simulations was
12
+ reignited! The game has a [full circuitry system](http://www.minecraftwiki.net/wiki/Redstone_circuits) for doing all sorts of fun logical
13
+ processing based on the most primitive inputs. But Minecraft is much better
14
+ as a game than as a learning environment, and it can be a very frustrating
15
+ and tedious environment to try to study circuitry in. I want a tool that
16
+ doesn't make me afraid of being attacked by zombies while I build my logic
17
+ gates!
18
+
19
+ In this exercise, I would like you to build a tool that makes exploring
20
+ digital circuitry fun and interesting. The summary below provides some
21
+ suggestions on what things in particular I have in mind, but everyone
22
+ should be able to come up with their own unique take on the idea without
23
+ too much overlap.
24
+
25
+ ## Exercise Summary
26
+
27
+ - You should create a tool that makes exploring and learning about
28
+ logical circuitry fun and interesting.
29
+ - You can use the "All Wired Up" problem and MineCraft's Redstone circuits
30
+ as an inspiration, but be sure to have some fresh ideas of your own.
31
+ - You should be able to build modular gates that can be re-used in other circuits.
32
+ - The way you handle input and output visualization is completely up to
33
+ you
34
+ - Your tool should be easy to work with for someone who wants to explore circuitry but is not necessarily a programmer.
35
+ - It should be possible to assign inputs, evaluate the circuits, and then inspect their outputs.
36
+ - Some sort of friendly debugging process and tools would be nice to have.
37
+
38
+ ## Submission Guidelines
39
+
40
+ If you plan to work on this exercise, you should fork this repository
41
+ and push code early and often during the course. The course
42
+ guidelines PDF explains the submission process in detail, but please
43
+ contact an instructor if you have any questions.
@@ -0,0 +1,11 @@
1
+ require "rake/testtask"
2
+
3
+
4
+ task :default => "test"
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList["test/*_test.rb"]
9
+ t.verbose = true
10
+ end
11
+
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "logicle"
4
+
5
+
6
+ USAGE_MESSAGE = "logicle <CIRCUIT FILE TO SOLVE> "
7
+
8
+
9
+ # Exit with usage message if user forgets to provide an input file.
10
+ Kernel.abort(USAGE_MESSAGE) if ARGV.length == 0
11
+
12
+
13
+ # Capture inputs from the command line.
14
+ circuit_file = ARGV.shift
15
+
16
+
17
+ # Instantiate the Logicle::Simulator instance.
18
+ simulator = Logicle::Simulator.new(circuit_file)
19
+ puts "Loaded main circuit from file: #{ circuit_file }"
20
+
21
+
22
+ # Prompt the user to enter states for each of the switch inputs.
23
+ switches = simulator.inputs
24
+ puts "The circuit to be solved requires #{ switches.count } input values (on/off)."
25
+
26
+ switches.each_with_index do |switch, index|
27
+ $stdout.printf("Switch %d on? (Y/n):>> ", index + 1)
28
+ input = $stdin.gets.chomp.downcase.chars.first
29
+ case input
30
+ when "y"
31
+ switch.type = :on
32
+ when "n"
33
+ switch.type = :off
34
+ else
35
+ puts "Invalid input!"
36
+ redo
37
+ end
38
+ end
39
+
40
+
41
+ # Evaluate the circuit.
42
+ simulator.evaluate
43
+ bulbs = simulator.outputs
44
+
45
+
46
+ # Print out the bulb states.
47
+ bulbs.each_with_index do |bulb, i|
48
+ puts "Bulb \##{ i + 1 }: #{ bulb.state ? "on" : "off" }"
49
+ end
50
+
51
+
52
+ # Ask the user to save the result file.
53
+ $stdout.write "Save output? (y/N): "
54
+ save_output_flag = $stdin.gets.chomp
55
+
56
+ if save_output_flag =~ /\Ay/i
57
+ output_filename = File.realdirpath(circuit_file).sub(/\.tgf\Z/, "_solved.tgf")
58
+ simulator.save(output_filename)
59
+ end
@@ -0,0 +1,14 @@
1
+ 1 NOT
2
+ 2 AND
3
+ 3 OR
4
+ 4 SWITCH
5
+ 5 SWITCH
6
+ 6 SWITCH
7
+ 7 BULB
8
+ #
9
+ 4 1
10
+ 5 2
11
+ 6 2
12
+ 2 3
13
+ 1 3
14
+ 3 7
@@ -0,0 +1,14 @@
1
+ 1 NOT (OFF)
2
+ 2 AND (ON)
3
+ 3 OR (ON)
4
+ 4 SWITCH (ON)
5
+ 5 SWITCH (ON)
6
+ 6 SWITCH (ON)
7
+ 7 BULB (ON)
8
+ #
9
+ 4 1
10
+ 5 2
11
+ 6 2
12
+ 2 3
13
+ 1 3
14
+ 3 7
@@ -0,0 +1,20 @@
1
+ require_relative "logicle/version"
2
+ require_relative "logicle/logicle"
3
+ require_relative "logicle/simulator"
4
+ require_relative "logicle/tgf_reader"
5
+ require_relative "logicle/tgf_writer"
6
+
7
+ require_relative "logicle/node"
8
+ require_relative "logicle/digraph"
9
+
10
+ module Logicle
11
+
12
+ # Raised when trying to create an edge in the graph to or from an unknown node
13
+ class UnknownNodeError < StandardError; end
14
+
15
+ # Raised in case of error while reading an input file
16
+ class ParseError < StandardError; end
17
+
18
+ # Raised when trying to create a node with an unknown type.
19
+ class UnknownNodeTypeError < StandardError; end
20
+ end
@@ -0,0 +1,53 @@
1
+ module Logicle
2
+ class Digraph
3
+ attr_reader :nodes, :edges
4
+
5
+ def initialize
6
+ @nodes, @edges = {}, {}
7
+ end
8
+
9
+ def evaluate
10
+ outputs.each_value do |output|
11
+ output.state
12
+ end
13
+ end
14
+
15
+ def inputs
16
+ @nodes.select { |id, node| node.switch? }
17
+ end
18
+
19
+ def outputs
20
+ @nodes.select { |id, node| node.bulb? }
21
+ end
22
+
23
+ def add_node(id, node_type)
24
+ @nodes[id] = Node.new(id, node_type)
25
+ end
26
+
27
+ def add_edge(start_id, end_id)
28
+ start_node, end_node = @nodes[start_id], @nodes[end_id]
29
+
30
+ if start_node && end_node
31
+ end_node.append_input(start_node)
32
+ @edges[start_id] = end_id
33
+ true
34
+ else
35
+ raise_unknown_nodes(start_id => start_node, end_id => end_node)
36
+ end
37
+ end
38
+
39
+ private
40
+ def raise_unknown_nodes(node_map={})
41
+ bad_node_ids = node_map.select { |id, node| node.nil? }.keys
42
+
43
+ case bad_node_ids.count
44
+ when 0
45
+ return
46
+ when 1
47
+ raise UnknownNodeError, "Invalid node id: #{ bad_node_ids[0] }"
48
+ else
49
+ raise UnknownNodeError, "Invalid node ids: #{ bad_node_ids.join(", ") }"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module Logicle
2
+ FILE_SUFFIX = ".tgf"
3
+ end
@@ -0,0 +1,65 @@
1
+ module Logicle
2
+ class Node
3
+ LOGIC_OPERATIONS = {
4
+ switch: Proc.new { |args| nil },
5
+ bulb: Proc.new { |args| args[0].state },
6
+ on: Proc.new { |args| true },
7
+ off: Proc.new { |args| false },
8
+ not: Proc.new { |args| !args[0].state },
9
+ and: Proc.new { |args| args[0].state & args[1].state },
10
+ or: Proc.new { |args| args[0].state | args[1].state },
11
+ nand: Proc.new { |args| !args[0].state | !args[1].state },
12
+ nor: Proc.new { |args| !args[0].state & !args[1].state },
13
+ xor: Proc.new { |args| args[0].state ^ args[1].state },
14
+ xnor: Proc.new { |args| !(args[0].state ^ args[1].state) }
15
+ }
16
+
17
+ attr_reader :id, :type, :inputs
18
+
19
+ def initialize(id, type)
20
+ @id = id
21
+ @type = validate_type(type)
22
+ @inputs = []
23
+ end
24
+
25
+ def bulb?
26
+ @type == :bulb
27
+ end
28
+
29
+ def switch?
30
+ @type == :switch
31
+ end
32
+
33
+ def type=(new_type)
34
+ @type = validate_type(new_type)
35
+ end
36
+
37
+ def append_inputs(*nodes)
38
+ @inputs += nodes
39
+ end
40
+ alias_method :append_input, :append_inputs
41
+
42
+ def clear_inputs
43
+ @inputs = []
44
+ @state = nil
45
+ end
46
+
47
+ def state
48
+ @state ||= evaluate
49
+ end
50
+
51
+ private
52
+ def validate_type(type)
53
+ if LOGIC_OPERATIONS.keys.include?(type)
54
+ type
55
+ else
56
+ raise UnknownNodeTypeError, "Unknown node type: '#{ type }'"
57
+ end
58
+ end
59
+
60
+ def evaluate
61
+ operation = LOGIC_OPERATIONS[@type]
62
+ operation.call(@inputs)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,35 @@
1
+ module Logicle
2
+ class Simulator
3
+ attr_reader :circuit
4
+
5
+ def initialize(*circuits)
6
+ @circuit = load(circuits.shift)
7
+ unless circuits.empty?
8
+ @sub_circuits = circuits.map { |circuit_file| load(circuit_file) }
9
+ end
10
+ end
11
+
12
+ def inputs
13
+ @circuit.inputs.values
14
+ end
15
+
16
+ def outputs
17
+ @circuit.outputs.values
18
+ end
19
+
20
+ def evaluate
21
+ @circuit.evaluate
22
+ end
23
+
24
+ def save(output_file)
25
+ writer = TgfWriter.new(output_file, @circuit)
26
+ writer.write
27
+ end
28
+
29
+ private
30
+ def load(circuit_file)
31
+ reader = TgfReader.new(circuit_file)
32
+ @circuit = reader.parse
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,52 @@
1
+ module Logicle
2
+ class TgfReader
3
+ def initialize(input)
4
+ if File.exists?(input)
5
+ @contents = File.readlines(input) # read file for TGF content
6
+ else
7
+ @contents = input.lines # use string param as TGF content
8
+ end
9
+ end
10
+
11
+ def parse
12
+ @circuit = Digraph.new
13
+ still_reading_nodes = true
14
+
15
+ @contents.each do |line|
16
+ line.chomp!
17
+
18
+ if line =~ /\A#/
19
+ still_reading_nodes = false
20
+ elsif still_reading_nodes
21
+ node_directive(line)
22
+ else
23
+ edge_directive(line)
24
+ end
25
+ end
26
+
27
+ @circuit
28
+ end
29
+
30
+ private
31
+ def node_directive(text)
32
+ if text =~ /\A(\d+)\s+(.*)\Z/
33
+ id, label = $1, $2
34
+ @circuit.add_node(id, label.downcase.to_sym)
35
+ else
36
+ raise ParseError, "Unable to parse TGF node directive: '#{ text }'"
37
+ end
38
+ rescue UnknownNodeTypeError
39
+ raise ParseError, "Unknown node type in directive: '#{ label }'"
40
+ end
41
+
42
+ def edge_directive(text)
43
+ if text =~ /\A(\d+)\s+(\d+)\Z/
44
+ start, finish = $1, $2
45
+ @circuit.add_edge(start, finish)
46
+ else
47
+ raise ParseError, "Unable to parse TGF edge directive: '#{ text }'"
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,38 @@
1
+ module Logicle
2
+ class TgfWriter
3
+ def initialize(filename, circuit)
4
+ @output_file = File.open(filename, "w")
5
+ @circuit = circuit
6
+ end
7
+
8
+ def write
9
+ @circuit.nodes.values.each { |node| write_node(node) }
10
+
11
+ write_separator
12
+
13
+ @circuit.edges.each { |start, finish| write_edge(start, finish) }
14
+ end
15
+
16
+ private
17
+ def write_node(node)
18
+ id = node.id
19
+ type = case node.type
20
+ when :on, :off
21
+ "SWITCH"
22
+ else
23
+ node.type.to_s.upcase
24
+ end
25
+ state = node.state ? "ON" : "OFF"
26
+
27
+ @output_file.puts "#{ id } #{ type } (#{ state })"
28
+ end
29
+
30
+ def write_separator
31
+ @output_file.puts "#"
32
+ end
33
+
34
+ def write_edge(start_id, end_id)
35
+ @output_file.puts "#{ start_id } #{ end_id }"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Logicle
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,23 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "logicle/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "logicle"
6
+ s.version = Logicle::VERSION
7
+ s.authors = ["Chris kottom"]
8
+ s.email = "chris@chriskottom.com"
9
+ s.homepage = ""
10
+ s.summary = %q{A simulator for playing with digital circuit logic}
11
+ s.description = %q{Logicle is a simulator for testing and solving simple circuits composed of basic logical elements. The program reads and writes its inputs and outputs using the GML protocol.}
12
+
13
+ s.rubyforge_project = "logicle"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = ["logicle"]
18
+ s.require_paths = ["lib", "vendor"]
19
+
20
+ # specify any dependencies here; for example:
21
+ # s.add_development_dependency "rspec"
22
+ # s.add_runtime_dependency "rest-client"
23
+ end
@@ -0,0 +1,34 @@
1
+ require_relative "test_helper"
2
+
3
+ require "test/unit"
4
+
5
+
6
+ class DigraphTest < Test::Unit::TestCase
7
+ include TestHelper
8
+
9
+ def test_add_node
10
+ start_node_count = digraph.instance_variable_get(:@nodes).count
11
+ digraph.add_node(1, :and)
12
+ assert_equal(start_node_count + 1,
13
+ digraph.instance_variable_get(:@nodes).count)
14
+ end
15
+
16
+ def test_add_edge
17
+ start_edge_count = digraph.instance_variable_get(:@edges).count
18
+ digraph.add_node(1, :and)
19
+ digraph.add_node(2, :or)
20
+ digraph.add_edge(1, 2)
21
+ assert_equal(start_edge_count + 1,
22
+ digraph.instance_variable_get(:@edges).count)
23
+
24
+ nodes = digraph.instance_variable_get(:@nodes)
25
+ assert(nodes[2].inputs.include?(nodes[1]))
26
+ end
27
+
28
+ def test_add_edge_with_unknown_node
29
+ assert_raises(Logicle::UnknownNodeError) do
30
+ digraph.add_node(1, :and)
31
+ digraph.add_edge(1, 2)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ require_relative "test_helper"
2
+
3
+ require "test/unit"
4
+
5
+
6
+ class LogicleTest < Test::Unit::TestCase
7
+
8
+ end
@@ -0,0 +1,92 @@
1
+ require_relative "test_helper"
2
+
3
+ require "test/unit"
4
+
5
+
6
+ class NodeTest < Test::Unit::TestCase
7
+ include TestHelper
8
+
9
+ def test_on_node
10
+ assert_equal(true, node(:on).state)
11
+ end
12
+
13
+ def test_off_node
14
+ assert_equal(false, node(:off).state)
15
+ end
16
+
17
+ def test_not_node
18
+ not_node = node(:not)
19
+ on_node = node(:on)
20
+ off_node = node(:off)
21
+
22
+ assert_node_state_for_inputs(false, not_node, on_node)
23
+ assert_node_state_for_inputs(true, not_node, off_node)
24
+ end
25
+
26
+ def test_and_node
27
+ and_node = node(:and)
28
+ on_node = node(:on)
29
+ off_node = node(:off)
30
+
31
+ assert_node_state_for_inputs(true, and_node, on_node, on_node)
32
+ assert_node_state_for_inputs(false, and_node, on_node, off_node)
33
+ assert_node_state_for_inputs(false, and_node, off_node, on_node)
34
+ assert_node_state_for_inputs(false, and_node, off_node, off_node)
35
+ end
36
+
37
+ def test_or_node
38
+ or_node = node(:or)
39
+ on_node = node(:on)
40
+ off_node = node(:off)
41
+
42
+ assert_node_state_for_inputs(true, or_node, on_node, on_node)
43
+ assert_node_state_for_inputs(true, or_node, on_node, off_node)
44
+ assert_node_state_for_inputs(true, or_node, off_node, on_node)
45
+ assert_node_state_for_inputs(false, or_node, off_node, off_node)
46
+ end
47
+
48
+ def test_nand_node
49
+ nand_node = node(:nand)
50
+ on_node = node(:on)
51
+ off_node = node(:off)
52
+
53
+ assert_node_state_for_inputs(false, nand_node, on_node, on_node)
54
+ assert_node_state_for_inputs(true, nand_node, on_node, off_node)
55
+ assert_node_state_for_inputs(true, nand_node, off_node, on_node)
56
+ assert_node_state_for_inputs(true, nand_node, off_node, off_node)
57
+ end
58
+
59
+ def test_nor_node
60
+ nor_node = node(:nor)
61
+ on_node = node(:on)
62
+ off_node = node(:off)
63
+
64
+ assert_node_state_for_inputs(false, nor_node, on_node, on_node)
65
+ assert_node_state_for_inputs(false, nor_node, on_node, off_node)
66
+ assert_node_state_for_inputs(false, nor_node, off_node, on_node)
67
+ assert_node_state_for_inputs(true, nor_node, off_node, off_node)
68
+ end
69
+
70
+ def test_xor_node
71
+ xor_node = node(:xor)
72
+ on_node = node(:on)
73
+ off_node = node(:off)
74
+
75
+ assert_node_state_for_inputs(false, xor_node, on_node, on_node)
76
+ assert_node_state_for_inputs(true, xor_node, on_node, off_node)
77
+ assert_node_state_for_inputs(true, xor_node, off_node, on_node)
78
+ assert_node_state_for_inputs(false, xor_node, off_node, off_node)
79
+ end
80
+
81
+ def test_xnor_node
82
+ xnor_node = node(:xnor)
83
+ on_node = node(:on)
84
+ off_node = node(:off)
85
+
86
+ assert_node_state_for_inputs(true, xnor_node, on_node, on_node)
87
+ assert_node_state_for_inputs(false, xnor_node, on_node, off_node)
88
+ assert_node_state_for_inputs(false, xnor_node, off_node, on_node)
89
+ assert_node_state_for_inputs(true, xnor_node, off_node, off_node)
90
+ end
91
+
92
+ end
@@ -0,0 +1,14 @@
1
+ 1 NOT
2
+ 2 AND
3
+ 3 OR
4
+ 4 SWITCH
5
+ 5 SWITCH
6
+ 6 SWITCH
7
+ 7 BULB
8
+ #
9
+ 4 1
10
+ 5 2
11
+ 6 2
12
+ 2 3
13
+ 1 3
14
+ 3 7
@@ -0,0 +1,40 @@
1
+ require_relative "../lib/logicle.rb"
2
+
3
+ module TestHelper
4
+ def node(type, id=1)
5
+ Logicle::Node.new(id, type)
6
+ end
7
+
8
+ def digraph
9
+ @digraph ||= Logicle::Digraph.new
10
+ end
11
+
12
+ def assert_node_state_for_inputs(value, target_node, *inputs)
13
+ target_node.clear_inputs
14
+ target_node.append_inputs(*inputs)
15
+ assert_equal(value, target_node.state)
16
+ end
17
+
18
+ def tgf_reader(input=tgf_content)
19
+ @tgf_reader ||= Logicle::TgfReader.new(input)
20
+ end
21
+
22
+ def tgf_content
23
+ @tgf_content ||= <<-TGF.gsub(/^\s+/, "")
24
+ 1 NOT
25
+ 2 AND
26
+ 3 OR
27
+ 4 SWITCH
28
+ 5 SWITCH
29
+ 6 SWITCH
30
+ 7 BULB
31
+ #
32
+ 4 1
33
+ 5 2
34
+ 6 2
35
+ 2 3
36
+ 1 3
37
+ 3 7
38
+ TGF
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ require_relative "test_helper"
2
+
3
+ require "test/unit"
4
+
5
+
6
+ class TgfReaderTest < Test::Unit::TestCase
7
+ include TestHelper
8
+
9
+ def test_initialization_with_filename
10
+ filename = File.join(File.dirname(__FILE__), "simple.tgf")
11
+ file_content = File.readlines(filename)
12
+
13
+ assert_equal(file_content,
14
+ tgf_reader(filename).instance_variable_get(:@contents))
15
+ end
16
+
17
+ def test_initialization_with_string
18
+ assert_equal(tgf_content.lines.to_a,
19
+ tgf_reader.instance_variable_get(:@contents).to_a)
20
+ end
21
+
22
+ def test_parsing
23
+ circuit = tgf_reader.parse
24
+
25
+ node_lines, edge_lines = tgf_content.split(/#\s*\n/)
26
+
27
+ assert_equal(node_lines.chomp.lines.count,
28
+ circuit.instance_variable_get(:@nodes).count)
29
+ assert_equal(edge_lines.lines.count,
30
+ circuit.instance_variable_get(:@edges).count)
31
+ end
32
+
33
+ def test_parsing_with_bad_node_type
34
+ content = "0 FOO\n" << tgf_content
35
+ assert_raises(Logicle::ParseError) do
36
+ tgf_reader(content).parse
37
+ end
38
+ end
39
+
40
+ def test_parsing_with_bad_edge
41
+ content = tgf_content << "\n10000 100001"
42
+ assert_raises(Logicle::ParseError) do
43
+ tgf_reader(content).parse
44
+ end
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logicle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris kottom
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-24 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Logicle is a simulator for testing and solving simple circuits composed
15
+ of basic logical elements. The program reads and writes its inputs and outputs using
16
+ the GML protocol.
17
+ email: chris@chriskottom.com
18
+ executables:
19
+ - logicle
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - .gitignore
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - README.md
27
+ - Rakefile
28
+ - bin/logicle
29
+ - examples/simple.tgf
30
+ - examples/simple_solved.tgf
31
+ - lib/logicle.rb
32
+ - lib/logicle/digraph.rb
33
+ - lib/logicle/logicle.rb
34
+ - lib/logicle/node.rb
35
+ - lib/logicle/simulator.rb
36
+ - lib/logicle/tgf_reader.rb
37
+ - lib/logicle/tgf_writer.rb
38
+ - lib/logicle/version.rb
39
+ - logicle.gemspec
40
+ - test/digraph_test.rb
41
+ - test/logicle_test.rb
42
+ - test/node_test.rb
43
+ - test/simple.tgf
44
+ - test/test_helper.rb
45
+ - test/tgf_reader_test.rb
46
+ homepage: ''
47
+ licenses: []
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ - vendor
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project: logicle
67
+ rubygems_version: 1.8.10
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: A simulator for playing with digital circuit logic
71
+ test_files: []