Ada*_*tan 35 python language-agnostic code-golf state-machine
确定性有限状态机是一种简单的计算模型,广泛用作基础CS课程中自动机理论的介绍.它是一个简单的模型,相当于正则表达式,它确定某个输入字符串是Accepted还是Rejected.抛开一些手续,有限状态机的运行包括:
一个运行在机器上开始处于起步状态.读取输入字符串的每个字母; 如果当前状态与对应于该字母的另一个状态之间存在转换,则当前状态将更改为新状态.在读取最后一个字母后,如果当前状态是接受状态,则接受输入字符串.如果最后一个状态不是接受状态,或者一个字母在运行期间没有来自状态的相应拱门,则拒绝输入字符串.
注意:这种短暂的破坏远不是FSM的完整,正式的定义; 维基百科的精彩文章是对该主题的精彩介绍.
例如,以下机器告知从左到右读取的二进制数是否具有偶数个0s:

{0,1}.(S1, 0) -> S2,(S1, 1) -> S1,(S2, 0) -> S1和(S2, 1) -> S2.使用您选择的语言实施FSM.
FSM应接受以下输入:
<States> List of state, separated by space mark.
The first state in the list is the start state.
Accepting states begin with a capital letter.
<transitions> One or more lines.
Each line is a three-tuple:
origin state, letter, destination state)
<input word> Zero or more characters, followed by a newline.
Run Code Online (Sandbox Code Playgroud)
例如,上述具有1001010输入字符串的机器将被写为:
S1 s2
S1 0 s2
S1 1 S1
s2 0 S1
s2 1 s2
1001010
Run Code Online (Sandbox Code Playgroud)
FSM的运行,写成<State> <letter> -> <state>,然后是最终状态.示例输入的输出将是:
S1 1 -> S1
S1 0 -> s2
s2 0 -> S1
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
s2 0 -> S1
ACCEPT
Run Code Online (Sandbox Code Playgroud)
对于空输入'':
S1
ACCEPT
Run Code Online (Sandbox Code Playgroud)
注意:在您的注释之后,S1可能会省略该行(显示第一个状态),并且以下输出也是可接受的:
ACCEPT
Run Code Online (Sandbox Code Playgroud)
用于101:
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
REJECT
Run Code Online (Sandbox Code Playgroud)
用于'10X':
S1 1 -> S1
S1 0 -> s2
s2 X
REJECT
Run Code Online (Sandbox Code Playgroud)
最短的解决方案将获得250个代表奖金.
这里提供了一个参考Python实现.请注意,空字符串输入已放宽输出要求.
根据大众需求,以下输出也可用于空输入字符串:
ACCEPT
Run Code Online (Sandbox Code Playgroud)
要么
REJECT
Run Code Online (Sandbox Code Playgroud)
没有在前一行写的第一个状态.
有效状态的名字是英文字母后跟任意数量的字母,_以及数字,很像变量的名称,例如State1,state0,STATE_0.
像大多数代码高尔夫球一样,您可以假设您的输入是正确的.
的sed137溶液是最短的,红宝石145是#2.目前,我无法获得sed解决方案:
cat test.fsm | sed -r solution.sed
sed -r solution.sed test.fsm
Run Code Online (Sandbox Code Playgroud)
两个都给了我:
sed: -e expression #1, char 12: unterminated `s' command
Run Code Online (Sandbox Code Playgroud)
所以,除非有澄清,否则赏金将归入红宝石解决方案.
Nas*_*nov 23
PS.问题放松后(无需在空输入上输出状态行),这里的新代码明显更短.如果你的版本是<2.7,那么就没有dict理解,所以不要{c+o:s for o,c,s in i[1:-1]}试试dict((c+o,s)for o,c,s in i[1:-1])+5的价格.
import sys
i=map(str.split,sys.stdin)
s=i[0][0]
for c in''.join(i[-1]):
if s:o=s;s={c+o:s for o,c,s in i[1:-1]}.get(c+s,());print o,c,'->',s
print'ARCECJEEPCTT'[s>'Z'::2]
Run Code Online (Sandbox Code Playgroud)
其测试输出:
# for empty input
ACCEPT
# for input '1001010'
S1 1 -> S1
S1 0 -> s2
s2 0 -> S1
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
s2 0 -> S1
ACCEPT
# for input '101'
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
REJECT
# for input '10X'
S1 1 -> S1
S1 0 -> s2
s2 X -> ()
REJECT
# for input 'X10'
S1 X -> ()
REJECT
Run Code Online (Sandbox Code Playgroud)
之前的条目(len 201):
import sys
i=list(sys.stdin)
s=i[0].split()[0]
t={}
for r in i[1:-1]:a,b,c=r.split();t[a,b]=c
try:
for c in i[-1]:print s,c.strip(),;s=t[s,c];print' ->',s
except:print('ACCEPT','REJECT')[s>'Z'or' '<c]
Run Code Online (Sandbox Code Playgroud)
我想在有人抨击我之前道歉:代码行为与原始规范略有不同 - 每个问题 - 评论讨论.这是我讨论的插图.
PS.虽然我喜欢与最终状态在同一行上的ACCEPT/REJECT分辨率,但我可以通过添加'\n'+(5个字符)来移动到孤独(例如想象结果将由愚蠢的脚本解析,只关心最后一行是接受还是拒绝))到最后print的+5个字符的价格.
示例输出:
# for empty input
S1 ACCEPT
# for input '1001010'
S1 1 -> S1
S1 0 -> s2
s2 0 -> S1
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
s2 0 -> S1
S1 ACCEPT
# for input '101'
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
s2 REJECT
# for input '10X'
S1 1 -> S1
S1 0 -> s2
s2 X REJECT
# for input 'X10'
S1 X REJECT
Run Code Online (Sandbox Code Playgroud)
Joe*_*ger 21
我今天感觉很复古,我的选择语言是IBM Enterprise Cobol - 字数2462 4078(对不起,从屏幕导向设备粘贴,尾随空间是一个悲剧性的副作用):
Identification Division.
Program-ID. FSM.
Environment Division.
Data Division.
Working-Storage Section.
01 FSM-Storage.
*> The current state
05 Start-State Pic X(2).
05 Next-State Pic X(2).
*> List of valid states
05 FSM-State-Cnt Pic 9.
05 FSM-States Occurs 9
Pic X(2).
*> List of valid transitions
05 FSM-Trans-Cnt Pic 999.
05 FSM-Trans Occurs 999.
10 Trans-Start Pic X(2).
10 Trans-Char Pic X.
10 Trans-End Pic X(2).
*> Input
05 In-Buff Pic X(72).
*> Some work fields
05 II Pic s9(8) binary.
05 JJ Pic s9(8) binary.
05 Wk-Start Pic X(2).
05 Wk-Char Pic X.
05 Wk-End Pic X(2).
05 Wk-Cnt Pic 999.
05 Pic X value ' '.
88 Valid-Input value 'V'.
05 Pic X value ' '.
88 Valid-State value 'V'.
05 Pic X value ' '.
88 End-Of-States value 'E'.
05 Pic X value ' '.
88 Trans-Not-Found value ' '.
88 Trans-Found value 'T'.
Linkage Section.
01 The-Char-Area.
05 The-Char Pic X.
88 End-Of-Input value x'13'.
05 The-Next-Char Pic X.
Procedure Division.
Perform Load-States
Perform Load-Transitions
Perform Load-Input
Perform Process-Input
Goback.
*> Run the machine...
Process-Input.
Move FSM-States (1) to Start-State
Set address of The-Char-Area to address of In-Buff
Perform until End-Of-Input
Perform Get-Next-State
Set address of The-Char-Area to address of The-Next-Char
Move Next-State to Start-State
End-Perform
If Start-State (1:1) is Alphabetic-Lower
Display 'REJECT'
Else
Display 'ACCEPT'
End-If
Exit.
*> Look up the first valid transition...
Get-Next-State.
Set Trans-Not-Found to true
Perform varying II from 1 by 1
until (II > FSM-State-Cnt)
or Trans-Found
If Start-State = Trans-Start (II)
and The-Char = Trans-Char (II)
Move Trans-End (II) to Next-State
Set Trans-Found to true
End-If
End-Perform
Display Start-State ' ' The-Char ' -> ' Next-State
Exit.
*> Read the states in...
Load-States.
Move low-values to In-Buff
Accept In-Buff from SYSIN
Move 0 to FSM-State-Cnt
Unstring In-Buff
delimited by ' '
into FSM-States (1) FSM-States (2) FSM-States (3)
FSM-States (4) FSM-States (5) FSM-States (6)
FSM-States (7) FSM-States (8) FSM-States (9)
count in FSM-State-Cnt
End-Unstring
Exit.
*> Read the transitions in...
Load-Transitions.
Move low-values to In-Buff
Accept In-Buff from SYSIN
Perform varying II from 1 by 1
until End-Of-States
Move 0 to Wk-Cnt
Unstring In-Buff
delimited by ' '
into Wk-Start Wk-Char Wk-End
count in Wk-Cnt
End-Unstring
If Wk-Cnt = 3
Add 1 to FSM-Trans-Cnt
Move Wk-Start to Trans-Start (FSM-Trans-Cnt)
Move Wk-Char to Trans-Char (FSM-Trans-Cnt)
Move Wk-End to Trans-End (FSM-Trans-Cnt)
Move low-values to In-Buff
Accept In-Buff from SYSIN
Else
Set End-Of-States to true
End-If
End-Perform
Exit.
*> Fix input so it has newlines...the joys of mainframes
Load-Input.
Perform varying II from length of In-Buff by -1
until Valid-Input
If In-Buff (II:1) = ' ' or In-Buff (II:1) = low-values
Move x'13' to In-Buff (II:1)
Else
Set Valid-Input to true
End-If
End-Perform
Exit.
End Program FSM.
Run Code Online (Sandbox Code Playgroud)
Nab*_*abb 19
这是使用-r标志(+3),总共134 + 3 = 137个字符.
$!{H;D}
/:/!{G;s/(\S*)..(\S*)/\2 \1:/}
s/(.* .)(.*\n\1 (\S*))/\1 -> \3\n\3 \2/
/-/{P;D}
/^[A-Z].* :/cACCEPT
s/( .).*/\1/
/:/!P
cREJECT
Run Code Online (Sandbox Code Playgroud)
这应该处理没有正确转换的输入...希望它现在完全符合规范......
h={}
o=s=p
$<.map{|l|o,b,c=l.split;h[[o,b]]=c;s||=o}
o.chars{|c|puts s+' '+c+((s=h[[s,c]])?' -> '+s :'')}rescue 0
puts s&&s<'['?:ACCEPT: :REJECT
Run Code Online (Sandbox Code Playgroud)
[
"S1 s2
S1 0 s2
S1 1 S1
s2 0 S1
s2 1 s2
1001010",
"S1 s2
S1 0 s2
S1 1 S1
s2 0 S1
s2 1 s2
101",
"S1 s2
S1 0 s2
S1 1 S1
s2 0 S1
s2 1 s2
",
"S1 s2
S1 0 s2
S1 1 S1
s2 0 S1
s2 1 s2
10X"
].each do |b|
puts "------"
puts "Input:"
puts b
puts
puts "Output:"
puts `echo "#{b}" | ruby fsm-golf.rb`
puts "------"
end
Run Code Online (Sandbox Code Playgroud)
所有输入都以:
S1 s2
S1 0 s2
S1 1 S1
s2 0 S1
s2 1 s2
Run Code Online (Sandbox Code Playgroud)
Input: '1001010'
Output:
S1 1 -> S1
S1 0 -> s2
s2 0 -> S1
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
s2 0 -> S1
ACCEPT
Input: '101'
Output:
S1 1 -> S1
S1 0 -> s2
s2 1 -> s2
REJECT
Input: 'X10'
Output:
S1 X
REJECT
Input: ''
Output:
ACCEPT
Input: '10X'
Output:
S1 1 -> S1
S1 0 -> s2
s2 X
REJECT
Run Code Online (Sandbox Code Playgroud)
Adam提供了参考实现.在我制作之前我没有看到它,但逻辑是相似的:
编辑:这是Python 2.6代码.我没有尽量减少长度; 我只是试图让它在概念上变得简单.
import sys
a = sys.stdin.read().split('\n')
states = a[0].split()
transitions = a[1:-2]
input = a[-2]
statelist = {}
for state in states:
statelist[state] = {}
for start, char, end in [x.split() for x in transitions]:
statelist[start][char] = end
state = states[0]
for char in input:
if char not in statelist[state]:
print state,char
print "REJECT"
exit()
newstate = statelist[state][char]
print state, char, '->', newstate
state = newstate
if state[0].upper() == state[0]:
print "ACCEPT"
else:
print "REJECT"
Run Code Online (Sandbox Code Playgroud)