# 优化SKI编译器

22

SKI演算是不使用Lambda表达式lambda演算的变体。相反，只有应用程序和组合器SK，和使用。在此挑战中，您的任务是将SKI术语转换为β范式的 Lambda术语。

## 输入规格

``````sterm = sterm combinator     ; application
sterm = combinator           ;
sterm = '(' sterm ')'        ; grouping
combinator = 'S' | 'K' | 'I' ; primitives
``````

## 输出规格

``````lterm   = lterm operand     ; application
lterm   = ALPHA '.' lterm   ; lambda
lterm   = operand
operand = '(' lterm ')'     ; grouping
operand = ALPHA             ; variable (a letter)
``````

## 样本输入

``````input                        output
I                            a.a
SKK                          a.a
KSK                          a.b.c.ac(bc)
SII                          a.aa
``````

## 计分

7
+1是因为我认为这是一个很酷的挑战；我什么都不懂。
Alex A.

2

@PeterTaylor这样更好吗？
FUZxxl

3

``````data T s=T{a::T s->T s,(%)::s}
i d=T(i. \x v->d v++'(':x%v++")")d
l f=f`T`\v->v:'.':f(i(\_->[v]))%succ v
b"S"x=l\$l.(a.a x<*>).a
b"K"x=l(\_->x)
b"I"x=x
p?'('=l id:p
(p:q:r)?')'=a q p:r
(p:q)?v=a p(l\$b[v]):q
((%'a')=<<).foldl(?)[l id]``````

9

# Ruby，323个字节

``````h={};f=96;z=gets.chop
{?S=>'s0.t0.u0.s0u0(t0u0)',?K=>'k0.l0.k0',?I=>'i0.i0'}.each{|k,v|z.gsub!k,?(+v+?)}
loop{z=~/\((?<V>\w1*0)\.(?<A>(?<B>\w1*0|[^()]|\(\g<B>+\))+)\)(?<X>\g<B>)/
s=\$`;t=\$';abort z.gsub(/\w1*0/){|x|h[x]=h[x]||(f+=1).chr}if !t
z=\$`+?(+\$~[?A].gsub(\$~[?V],\$~[?X].gsub(/\w1*0/){|a|s[a]?a:a.gsub(?0,'10')})+?)+t}
``````

``````\$ echo 'I' | ruby ski.rb
(a.a)
\$ echo 'SKK' | ruby ski.rb
(a.(a))
\$ echo 'KSK' | ruby ski.rb
((a.b.c.ac(bc)))
\$ echo 'SII' | ruby ski.rb
(a.(a)((a)))
``````

``````\$ echo 'K(K(K(KK)))' | ruby ski.rb
"(l0.((k10.l10.k10)((k10.l10.k10)((k10.l10.k10)(k10.l10.k10)))))"
"(l0.((l10.((k110.l110.k110)((k110.l110.k110)(k110.l110.k110))))))"
"(l0.((l10.((l110.((k1110.l1110.k1110)(k1110.l1110.k1110)))))))"
"(l0.((l10.((l110.((l1110.(k11110.l11110.k11110))))))))"
(a.((b.((c.((d.(e.f.e))))))))
``````

2

9

# Python 2，674

``````exec u"""import sys
\$ V#):%=V.c;V.c+=1
c=97;p!,v,t:[s,t.u({})][v==s];r!:s;u!,d:d.get(s,s);s!:chr(%)
def m(s,x):%=min(%,x);-(%==x)+x
\$ A#,*x):%,&=x
C='()';p!,x,y:s.__\$__(%.p/,&.p/);m!,x:&.m(%.m(x));u!,d:A(%.u(d),&.u(d));s!:%.s()+s.C[0]+&.s()+s.C[1:]
def r(s):x=%.r();y=&.r();-x.b.p(x.a,y).r()if'L'in`x`else s.__\$__/
\$ L(A):C='.';u!,d:L(d.setdefault(%,V()),&.u(d))
x=V();y=V();z=V()
I=L(x,x)
K=L(y,L/)
S=L(x,L(z,L(y,A(A/,A(z,y)))))
def E():
t=I
while 1:
if q in')\\n':-t
t=A(t,eval(max(q,'E()')).u({}))
t=E().r()
t.m(97)
print t.s()""".translate({33:u'=lambda s',35:u':\n def __init__(s',36:u'class',37:u's.a',38:u's.b',45:u'return ',47:u'(x,y)'})``````

V =变量项
A =应用程序项
L = lambda项
c =变量计数器
p =用项
r 替换变量r =减少
m =最终变量重编号
u =内部变量重编号（对于重复项）
s =字符串转换
（参数s =自变量）
C =用于字符串转换的分隔符
I，K，S：组合符
E =解析

``````python ski.py <<< "KSK"
a.b.c.a(c)(b(c))
python ski.py <<< "SII"
a.a(a)
python ski.py <<< "SS(SS)(SS)"
a.b.a(b)(c.b(c)(a(b)(c)))(a(d.a(d)(e.d(e)(a(d)(e))))(b))
python ski.py <<< "S(K(SI))K"
a.b.b(a)
python ski.py <<< "S(S(KS)K)I"
a.b.a(a(b))
python ski.py <<< "S(S(KS)K)(S(S(KS)K)I)"
a.b.a(a(a(b)))
python ski.py <<< "K(K(K(KK)))"
a.b.c.d.e.f.e
python ski.py <<< "SII(SII)"
[...]
RuntimeError: maximum recursion depth exceeded``````

（因为`SII(SII)`不可约，所以期望该↑ ）

1

@毛里斯感谢小费:)

coredump

@coredump是一个带有不必要分组的操作数...而您是对的，它与OP的语法规则不完全匹配。我想知道它有多重要？我会问的。

@coredump现在应该可以使用更新的语法了。

3

# 普通Lisp，560个字节

“最后，我找到了的用途`PROGV`。”

``(macrolet((w(S Z G #1=&optional(J Z))`(if(symbolp,S),Z(destructuring-bind(a b #1#c),S(if(eq a'L),G,J)))))(labels((r(S #1#(N 97))(w S(symbol-value s)(let((v(make-symbol(coerce`(,(code-char N))'string))))(progv`(,b,v)`(,v,v)`(L,v,(r c(1+ n)))))(let((F(r a N))(U(r b N)))(w F`(,F,U)(progv`(,b)`(,U)(r c N))))))(p()(do((c()(read-char()()#\)))q u)((eql c #\))u)(setf q(case c(#\S'(L x(L y(L z((x z)(y z))))))(#\K'(L x(L u x)))(#\I'(L a a))(#\((p)))u(if u`(,u,q)q))))(o(S)(w S(symbol-name S)(#2=format()"~A.~A"b(o c))(#2#()"~A(~A)"(o a)(o b)))))(lambda()(o(r(p))))))``

### 不打高尔夫球

``````;; Bind S, K and I symbols to their lambda-calculus equivalent.
;;
;; L means lambda, and thus:
;;
;; -  (L x S) is variable binding, i.e. "x.S"
;; -  (F x)   is function application

(define-symbol-macro S '(L x (L y (L z ((x z) (y z))))))
(define-symbol-macro K '(L x (L u x)))
(define-symbol-macro I '(L x x))

;; helper macro: used twice in R and once in O

(defmacro w (S sf lf &optional(af sf))
`(if (symbolp ,S) ,sf
(destructuring-bind(a b &optional c) ,S
(if (eq a 'L)
,lf
,af))))

;; R : beta-reduction

(defun r (S &optional (N 97))
(w S
(symbol-value s)
(let ((v(make-symbol(make-string 1 :initial-element(code-char N)))))
(progv`(,b,v)`(,v,v)
`(L ,v ,(r c (1+ n)))))
(let ((F (r a N))
(U (r b N)))
(w F`(,F,U)(progv`(,b)`(,U)(r c N))))))

;; P : parse from stream to lambda tree

(defun p (&optional (stream *standard-output*))
(loop for c = (read-char stream nil #\))
until (eql c #\))
for q = (case c (#\S S) (#\K K) (#\I I) (#\( (p stream)))
for u = q then `(,u ,q)
finally (return u)))

;; O : output lambda forms as strings

(defun o (S)
(w S
(princ-to-string S)
(format nil "~A.~A" b (o c))
(format nil (w b "(~A~A)" "(~A(~A))") (o a) (o b))))``````

### 减少Beta

``````(defun beta-reduce (S &optional (N 97))
(if (symbolp s)
(symbol-value s)
(if (eq (car s) 'L)
;; lambda
(let ((v (make-symbol (make-string 1 :initial-element (code-char N)))))
(progv (list (second s) v)(list v v)
`(L ,v ,(beta-reduce (third s) (1+ n)))))
(let ((fn (beta-reduce (first s) N))
(arg (beta-reduce (second s) N)))
(if (and(consp fn)(eq'L(car fn)))
(progv (list (second fn)) (list arg)
(beta-reduce (third fn) N))
`(,fn ,arg))))))``````

### 中间结果

``````CL-USER> (p (make-string-input-stream "K(K(K(KK)))"))
((L X (L U X)) ((L X (L U X)) ((L X (L U X)) ((L X (L U X)) (L X (L U X))))))
``````

``````CL-USER> (r *)
(L #:|a| (L #:|a| (L #:|a| (L #:|a| (L #:|a| (L #:|b| #:|a|))))))
``````

（请参阅执行痕迹）

``````CL-USER> (o *)
"a.a.a.a.a.b.a"
``````

### 测验

``````        Input                    Output              Python output (for comparison)

1.   KSK                      a.b.c.a(c)(b(c))    a.b.c.a(c)(b(c))
2.   SII                      a.a(a)              a.a(a)
3.   S(K(SI))K                a.b.b(a)            a.b.b(a)
4.   S(S(KS)K)I               a.b.a(a(b))         a.b.a(a(b))
5.   S(S(KS)K)(S(S(KS)K)I)    a.b.a(a(a(b)))      a.b.a(a(a(b)))
6.   K(K(K(KK)))              a.a.a.a.a.b.a       a.b.c.d.e.f.e
7.   SII(SII)                 ERROR               ERROR
``````

``````8.      SS(SS)(SS)
CL      a.b.a(b)(c.b(c)(a(b)(c)))(a(b.a(b)(c.b(c)(a(b)(c))))(b))
Python  a.b.a(b)(c.b(c)(a(b)(c)))(a(d.a(d)(e.d(e)(a(d)(e))))(b))
``````
• 编辑我更新了我的答案，以便与atsutsu的答案具有相同的分组行为，因为它花费的字节数更少。
• 其余的差异可以看出对于测试6和8的结果`a.a.a.a.a.b.a`是正确的，并尽可能多的字母Python的答案，在哪里绑定不使用`a``b``c``d`没有被引用。

### 性能

``````Evaluation took:
0.000 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
100.00% CPU
310,837 processor cycles
129,792 bytes consed
``````

FUZxxl 2015年

@FUZxxl谢谢！
coredump