Skip to content

Instantly share code, notes, and snippets.

@P403n1x87
Last active December 12, 2019 22:13
Show Gist options
  • Save P403n1x87/0641e1c17571243830ef4058b7fd05d7 to your computer and use it in GitHub Desktop.
Save P403n1x87/0641e1c17571243830ef4058b7fd05d7 to your computer and use it in GitHub Desktop.
class FiniteAutomaton:
def __init__(self):
self._states = {}
self._initial = None
self._current = None
def add_state(self, name, handler, initial=False):
if initial:
if self._initial:
raise RuntimeError("Initial state already added!")
self._initial = name
self._current = self._initial
self._states[name] = handler
def run(self, actions):
for action in actions:
self._current = self._states[self._current](action)
return self._current
from thirteen import Thirteen
SOURCE_3 = r"""// This file contains 3 lines of code
public interface Dave {
/**
* count the number of lines in a file
*/
int countLines(File inFile); // not the real signature!
}"""
SOURCE_5 = r"""/*****
* This is a test program with 5 lines of code
* \/* no nesting allowed!
//*****//***/// Slightly pathological comment ending...
public class Hello {
public static final void main(String [] args) { // gotta love Java
// Say hello
System./*wait*/out./*for*/println/*it*/("Hello/*");
}
}"""
SOURCE_7 = """class Main {
public static void main(String[] args) {
double test = 1.
/
5;
}
}"""
def test_thirteen():
t = Thirteen()
assert t.count_lines(SOURCE_3) == 3
assert t.count_lines(SOURCE_5) == 5
assert t.count_lines(SOURCE_7) == 7
from fsm import FiniteAutomaton as FA
class Thirteen(FA):
def __init__(self):
super().__init__()
# Configure the machine
self.add_state(
"N",
lambda a: {'"': "S", "/": "C?", " ": "B", "\t": "B", "\n": "N",}.get(
a, "C"
),
initial=True,
)
self.add_state("C", lambda a: {'"': "S", "/": "C?", "\n": "N"}.get(a, "C"))
self.add_state("S", lambda a: {"\\": "E", '"': "C"}.get(a, "S"))
self.add_state(
"B",
lambda a: {" ": "B", "\t": "B", "\n": "N", "/": "C?", '"': "S"}.get(a, "C"),
)
self.add_state("C?", lambda a: {"/": "SL", "*": "ML", "\n": "N"}.get(a, "C"))
self.add_state("E", lambda a: "S")
self.add_state("ML", lambda a: "?C" if a == "*" else "ML")
self.add_state("SL", lambda a: "N" if a == "\n" else "SL")
self.add_state("?C", lambda a: {"/": "B", "*": "?C"}.get(a, "ML"))
def count_lines(self, source):
seq = ["N"]
for char in source:
state = self.run(char)
if state in ["N", "C", "C?", "ML", "SL"] and state != seq[-1]:
seq.append(state)
return len(
[
line
for line in "".join(seq)
.replace("C?ML", "")
.replace("C?SL", "")
.split("N")
if line
]
)
if __name__ == "__main__":
t = Thirteen()
print(
t.count_lines(
"""
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
"""
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment