Basit Ters Lehçe Notasyonu Programlama Dili


24

Açıklama

Hayali programlama dili (IPL), Polonya Ters Notasyonu kullanır. Aşağıdaki komutlara sahiptir:

  • i - giriş numarasını girin ve yığına itin
  • o - yığının tahribatsız çıkış tepesi (sayı yığında kalır)
  • d - yığının üst kısmını at
  • tamsayı numarası - bu numarayı yığına itin
  • + - * - yığından iki sayı çıkar, ilgili işlemi gerçekleştir ve sonucu geriye it. IPL'de bölünme yoktur.

IPL sadece tamsayılarla çalışır ve basit hesaplamalar için kullanılır. Bir IPL programı bir satıra yazılır ve boşluklarla ayrılır. Boş dize geçerli bir IPL programıdır.

IPL Programı:

i i + o 

İki sayı girer, bunları bir araya getirir ve sonucu çıkarır.

Yığına itilebilecek giriş sayıları ve tam sayıları [-999, 999] aralığındadır, ancak çıktı herhangi olabilir. Diliniz büyük rakamları desteklemiyorsa, sorun değil.

Giriş / çıkış formatı

Dize, liste, belirteçler vb. Anlamak ve okumak / yazmak açık olduğu sürece herhangi bir giriş / çıkış formatını seçebilirsiniz.

Görev

Size bir IPL programı verildi, onu optimize etmeniz gerekiyor (uzunluğu azaltmanız):

i 12 + 3 + o d 2 3 + d

Optimizasyon sonra olacak

i 15 + o

Yığın durumunu korumak zorunda değilsiniz, ancak giriş ve çıkışların miktarı ve sıralaması orijinal ve optimize edilmiş program için eşleşmelidir.

Yani IPL programı:

-40 i * 2 * o i + 3 1 + o i 2 *

Optimizasyon sonra olacak

i -80 * o i 4 o i

veya

-80 i * o i 4 o i

(ilgisiz olsalar bile, tüm girişleri kaydetmeniz gerektiğini unutmayın).

Test durumları için kodlama yapılmamalı, kod herhangi bir IPL programında çalışmalı ve gereksinimleri karşılayan en kısa IPL programını oluşturmalıdır.

puanlama

Varsayılan kod-golf puanlaması.

GÜNCELLEME: @Sanchises önerisine göre puanlamayı saf kod golf puanlamasına değiştirdi.

Test durumları:

Giriş:

(empty string)

Mümkün çıktı:

(empty string)

Giriş:

i 4 * 2 + 3 * 6 - o

Mümkün çıktı:

i 12 * o

Giriş:

1 1 + o

Mümkün çıktı:

2 o

Giriş:

i 2 + 3 + o d 2 3 + d

Mümkün çıktı:

i 5 + o

Giriş:

-40 i * 2 * o i + 3 1 + o i 2 *

Mümkün çıktı:

-80 i * o i 4 o i

Giriş:

i i 1 + i 1 + i 1 + i 1 + d d d d o 

Mümkün çıktı:

i i i i i d d d d o 

Giriş:

i i i 0 * * * o

Mümkün çıktı:

i i i 0 o

Giriş:

i i i 1 * * * o

Mümkün çıktı:

i i i * * o

Giriş:

i 222 + i 222 - + o

Mümkün çıktı:

i i + o

Giriş:

i 2 + 3 * 2 + 3 * 2 + 3 * i * d i 2 + 3 * i + d i o 2 + 2 - 0 * 1 o

Mümkün çıktı:

i i i i i o 1 o

Giriş:

i 1 + 2 * 1 + o 

Mümkün çıktı:

i 2 * 3 + o

Giriş:

1 1 + o i 2 + 3 + o d 2 3 + d 4 i * 2 * o i + 3 1 + o i 2 * i i 1 + i 1 + i 1 + i 1 + d d d d o i i i 0 * * * o i i i 1 * * * o i 2 + i 2 - + o i 2 + 3 * 2 + 3 * 2 + 3 * i * d i 2 + 3 * i + d i o 2 + 2 - 0 * 1 o

Mümkün çıktı:

2 o i 5 + o 8 i * o i 4 o i i i i i i d d d d o i i i 0 o i i i * * * o i i + o i i i i i o 1 o

1
Bir soru: Eğer kolaylaştırabilirsiniz i i d oiçin i o i(giriş sırada bulunuyor ve çıkış sırada bulunuyor) ya da bunu basitleştirmek gerekmez mi? (giriş ve çıkışların sırası uygun olmalıdır)
Sanchises

1
@Sanchises hayır, girişler ve çıkışlar sırayla olmalıdır. Orijinal program, optimize edilmiş herhangi bir şey çıkarmadan önce 2 sayı giriyorsa, aynı şeyi yapmalıdır.
Андрей Ломакин

1
PPCG'ye Hoşgeldiniz! Güzel ilk Challenge!
Luis felipe De jesus Munoz

6
Gönderen inceleme kuyruğuna , bu meydan okuma belirsiz olduğunu düşünmüyorum. Yaparsanız, neden hakkında yorum yapın.
mbomb007 14

2
@WW OP, yalnızca soruda listelenen test durumlarını kodlamamanız gerektiği anlamına gelir. Keyfi girişi desteklemelisiniz. Test durumları için herhangi bir
mbomb007

Yanıtlar:


5

Wolfram Dili (Mathematica) , 733 728 690 564 516 506 513 548 bayt

j=Integer;f=Flatten;s=SequenceReplace;A=FixedPoint[f@s[#,{{x_j,p,y_j,t}->{y,t,x*y,p},{x_j,y_j,p}->x+y,{x_j,y_j,t}->x*y,{x_j,p,y_j,p}->{x+y,p},{x_j,t,y_j,t}->{x*y,t},{0,p}|{1,t}->{},{0,t}->{d,0}}]//.{a___,Except[i|o]}->{a}&,#]&;B=Expand@Check[f@FoldPairList[f/@Switch[#2,i,{{i},{#,i@c++}},o,{{Last@#},#},d,{{},Most@#},p,{{},{#[[;;-3]],Tr@#[[-2;;]]}},t,{{},{#[[;;-3]],#[[-2]]*Last@#}},_,{{},{##}}]&,c=0;{},#],x]&;F=MinimalBy[w=A@f[#/.m->{-1,t,p}];z=B@w;s[#,{-1,t,p}->m]&/@A/@Select[Permutations@Join[w,Cases[z /.i@_->i,_j,∞]],B@#==z&],Length][[1]]&

Çevrimiçi deneyin!

Bu, (1) "-" 'i "-1 * +" ile değiştiren dört aşamalı bir zorlamadır, böylece çıkarmalar ile uğraşmak zorunda kalmayız, (2) komut listesini biraz basitleştirir, ( 3) bu komut listesindeki tüm permütasyonların bir listesini yapar ve ayrıştırıldığında (çalıştırıldığında) aynı sonucu verenleri seçer ve (4) bu komut listelerini bir miktar basitleştirir ve en kısa zamanda belirli işlemleri geri dönüştürür. çıkarmalar.

Bu kod çok verimsizdir, çünkü giriş kodunun tüm izinleri listesinden geçer. Uzun giriş kodları için bu kodu çalıştırmanızı önermiyorum; ama okuduğum gibi bu mücadelede çalışma zamanı veya hafıza kısıtlaması yoktur.

Bu kod tüm "-" işlemleri "+" işlemlerine döndürülen işaretlerle dönüştürdükten sonra optimizasyon adımını uygular ve sonunda kodları dizgelere dönüştürürken sadece "-" operatörünü tekrar tanıtır. Bu, örneğin "i -1 i * + o" nun "ii - o" ya doğru şekilde optimize edildiğini gösterir.

G / Ç format gereksinimi oldukça gevşek olduğu için, bu kod, kodu "+", "-", "*" sembollerinin sırasıyla p, m, t, tokenlerle temsil edildiği listeler olarak alır ve listeler. Dizgelere ve dizgelere dönüşüm, TIO'da verilen sarmalayıcı işlevinde yapılır:

G[S_] := StringReplace[{"p" -> "+", "m" -> "-", "t" -> "*"}]@StringRiffle@
         Quiet@F@
         ToExpression[StringSplit[S] /. {"+" -> p, "-" -> m, "*" -> t}]

Dize formatı sargısı içeren ve belirteçlerin sayısı yerine son kod dizesi uzunluğunu en aza indirgeyen ve birkaç daha fazla dönüşüm nişanı içeren golfsüz versiyon:

(* convert code string to list of operators *)
inputfilter[s_] := ToExpression[Flatten[StringSplit[s] /.
  {"i" -> i, "o" -> o, "d" -> d, "+" -> p, "-" -> {-1, t, p}, "*" -> t}]]

(* convert list of operators to code string *)
outputfilter[s_] := StringReplace[StringRiffle@Flatten@SequenceReplace[s,
  {{-1, t, p} -> m,                         (* convert "-1 t p" back to "-"             *)
   {x_ /; x < 0, p} -> {-x, m},             (* convert "y x +" to "y -x -" when x<0     *)
   {x_ /; x < 0, t, p} -> {-x, t, m}}],     (* convert "y x * +" to "y -x * -" when x<0 *)
  {"m" -> "-", "p" -> "+", "t" -> "*"}]     (* backsubstitution of symbols              *)

(* simplify a list of operators somewhat *)
simplifier[s_] := FixedPoint[Flatten@SequenceReplace[#,
  {{x_Integer, p, y_Integer, t} -> {y, t, x*y, p},  (*  "x + y *" -> "y * (xy) +"       *)
   {x_Integer, y_Integer, p} -> x + y,              (*  "x y +" -> "(x+y)"              *)
   {x_Integer, y_Integer, t} -> x*y,                (*  "x y *" -> "(xy)"               *)
   {x_Integer, p, y_Integer, p} -> {x + y, p},      (*  "x + y +" -> "(x+y) +"          *)
   {x_Integer, t, y_Integer, t} -> {x*y, t},        (*  "x * y *" -> "(xy) *            *)
   {0, p} | {1, t} -> {},                           (*  "0 +" and "1 *" are deleted     *)
   {x_Integer, i, p} -> {i, x, p},                  (*  "x i +" -> "i x +"              *)
   {x_Integer, i, t} -> {i, x, t},                  (*  "x i *" -> "i x *"              *)
   {0, t} -> {d, 0}}] //.                           (*  "0 *" -> "d 0"                  *)
  {a___, Except[i | o]} -> {a} &, s]                (* delete trailing useless code     *)

(* execute a list of operators and return the list of generated outputs *)
parse[s_] := Expand@Quiet@Check[Flatten@FoldPairList[  (* stack faults are caught here     *)
  Function[{stack, command},                        (* function called for every command*)
    Flatten /@ Switch[command,                      (* code interpretation:             *)
    i, {{i}, {stack, i[inputcounter++]}},           (* output "i" and add input to stack*)
    o, {{stack[[-1]]}, stack},                      (* output top of stack              *)
    d, {{}, Most[stack]},                           (* delete top of stack              *)
    p, {{}, {stack[[;; -3]], stack[[-2]] + stack[[-1]]}},  (* add two stack elements    *)
    t, {{}, {stack[[;; -3]], stack[[-2]]*stack[[-1]]}},    (* multiply two stack elements*)
    _, {{}, {stack, command}}]],                    (* put number onto stack            *)
    inputcounter = 0; {},                           (* start with zero input counter and empty stack*)
    s],                                             (* loop over code list              *)
  x]                                                (* return "x" if an error occurred  *)

(* the main function that takes a code string and returns an optimized code string *)
F[s_] := Module[{w, q},
  w = simplifier@inputfilter@s;      (* convert input to useful form *)
  q = parse[w];                      (* execute input code *)
  MinimalBy[
    outputfilter@*simplifier /@      (* simplify and stringify selected codes          *)
      Select[Permutations[w],        (* all permutations of code list                  *)
             parse[#] == q &],       (* select only those that give the correct output *)
    StringLength] // Union]          (* pick shortest solution by length               *)

Böcek yakalamada @redundancy teşekkürler: ExpandDağıtıcı denkliği ele almak için ayrıştırıcının çıkışa uygulanması gerekir. 506 → 513

güncelleştirme

Şimdi de optimize 1 o 1 + oeder 1 o 2 o. Bu şaşırtıcı derecede zor bir durumdu ve kodu daha yavaş hale getirdi. 513 → 548


Bu gibi görünüyor test davasında bir hata veriyor i i 1 + i 1 + i 1 + i 1 + d d d d o.
Grimmy

@ Grimy dediğim gibi, bu kod büyük problemler için çalışmaz, çünkü kod uzayının kapsamlı bir birleşimini araştırır. Hata, TIO’da yetersiz bir hatadır ve kodum nedeniyle değil.
Roman

@Grimy "ii 1 + d o" için kodum, optimize edilmiş olduğunu düşündüğüm "iid o" kodunu veriyor. "İi 1 + i 1 + dd o" için, daha belirgin "iiidd o" optimizasyonu ile aynı sayıda belirteçlere sahip olan "iii + do" 'yu ​​verir. Daha uzun girişler denemedim.
Roman,

Girişin i 2 * i 2 * + oen iyi duruma getirilmiş çıktı üretmesi gerektiğine inanıyorum i i + 2 * o, ancak bu kod ( en iyi duruma getirilmemiş ) girişi döndürüyor.
fazlalık

Thanks @redundancy, sabittir ve örneğiniz şimdi dahil test durumlarından biridir.
Roman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.