Postfix Gösterimine Önek No


19

Yasal Uyarı: Hayır, bu bir dizeyi tersine çevirmek için bir şaka zorluğu değildir.

Görev

Desteklenecek tek bir işlem vardır: çıkarma ( -).

Ayrıca destekleyecek sadece iki atomunuz var: sıfır ( 0) ve bir ( 1).

Burada, önek gösterimi -ABpostfix göstergesine eşdeğerdir AB-, burada Ave Bifadelerdir.

Göreviniz, önek gösterimindeki bir ifadeyi postfix gösterimindeki eşdeğerine (yinelemeli olarak) dönüştürmektir.

Tanımlar

Ön ek gösterimindeki bir ifade aşağıdaki dilbilgisi tarafından oluşturulur:

S > -SS
S > 0
S > 1

Postfix gösterimindeki bir ifade aşağıdaki dilbilgisi tarafından oluşturulur:

S > SS-
S > 0
S > 1

Misal

Prefix notation:  --01-0-01
Parentheses:      -(-01)(-0(-01))
Convert:          (01-)(0(01-)-)-
Postfix notation: 01-001---

Kurallar ve özgürlük

  • İşlemi ve atomları, tutarlı olduğu sürece hangi karakterle yeniden adlandırabilirsiniz.
  • Girdi biçimi, çıktı biçimiyle tutarlı olmalıdır (girdinin önek gösteriminde ve çıkışın düzeltme sonrası gösteriminde olması dışında).

Test durumu

Input       Output
1           1
0           0
-01         01-
-10         10-
--01-0-01   01-001---

Kredi testcases Dada .


1
Birkaç test örneği daha ekleyebilir misiniz?
Shaggy

@Shaggy ne tür testcasları istersiniz?
Leaky Nun

@LeakyNun Cevabımın en son sürümünde yaptığım gibi, giriş ve çıkışı yineleyiciler olarak almak iyi mi?
L3viathan

@ L3viathan Sanırım öyle ...
Leaky Nun

Yanıtlar:


12

brainfuck , 32 bayt

,[[->++++<<+>]>[[-]<<[.[-]<]]>,]

Çevrimiçi deneyin!

@Kod noktası (64) uygun olduğundan işlem olarak kullandım . U3 * 85 + 1 = 256 = 0 kullanılarak aynı bayt sayımı ile de mümkündür.

açıklama

Bant yığın olarak kullanılır. Ana döngünün her yinelemesinde, veri işaretçisi yığının üstünden sağdaki iki hücreyi başlatır.

,[                Take input and start main loop
  [->++++<<+>]    Push input, and compute 4*input
  >[              If 4*input is nonzero (and thus input is not @):
    [-]<<           Zero out this cell and move to top of stack
    [.[-]<]         Pop from stack and output until \0 is reached
  ]
  >,              Move pointer into the correct position.  If input was @, the earlier > pushed \0 onto the stack.
]

6

Retina , 37 30 29 bayt

M!`-*.
+m`^-(.*)¶(\d.*)
$1$2-

Çevrimiçi deneyin! Terimlerin her zaman bir rakamla başladığını fark ederek 7 bayt kaydedildi, bu yüzden maçı artık son ile sınırlamak zorunda değilim -(daha önce iki terimle takip edileceği garanti edilen tek şey buydu). -Kendi baytına koymadan 1 bayt kaydedildi . Örneğin, -01daha -0¶1sonra olan ile değiştirilir 01-. Ben Şimdi, eğer --010ie --0¶1¶0sonra iç değiştirmek istiyorum -0¶1için 01-ben yerine böylece -01-¶0ile 01-0-, ama bu mesele aslında değil hangi ikinin arasında -lar ı kaldır gibi, satırın başında birini çıkarın Öyle test etmek daha kolay.


Sanırım bu senin bir şey :)
Leo

@Leo Genel olarak çalışmaz, örneğin -0-0-00olmalıdır 0000---.
Neil

Haklısın özür dilerim. Başka bir fikrim var, ama oldukça farklı, bu yüzden yeni bir cevap olarak
Leo

1
@Leo şimdi bir şey buldum ...
Neil

1
@Leo En son golf ile bağlandık!
Neil

6

Haskell , 62 59 bayt

f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
fst.f

Çevrimiçi deneyin! Kullanımı: fst.f $ "--01-0-01". 0ve 1karakterden daha büyük rastgele karakterler olabilir -.

Düzenleme: Zgarb sayesinde -3 bayt!

İşlev, fbir ifadeyi özyinelemeli olarak ayrıştırır ve geçerli önek ifadelerinin oluşturulabileceği basit dilbilgisini izleyerek postfix gösterimi ve geri kalanı dizesinde bu ifadenin bir demetini döndürür:

<exp> ::= - <exp> <exp> | 0 | 1

aGiriş dizesinin ilk karakteri daha büyükse -, atomik bir ifadedeyiz ve karakter içeren bir dizenin bir demetini ave giriş dizesinin geri kalanını döndürürüz.

Bir bulursak -, iki ifadenin ayrıştırılması gerekir. Bu (a,x)<-f r, ilk ifadeyi almak ave daha sonra ikinci ifadeyi ve son dinlenme dizesini elde etmek için dinlenme dizesini xtekrar ayrıştırmak suretiyle (b,c)<-f xelde edilebilir . tam olarak bunu yapar, çünkü tuples'de bir fonksiyonun iki fonksiyonunu, üç bayttan daha kısaken bir tupleın ikinci elemanı eşler . İfadeleri ve dinlenme dizesi hem alındıktan sonra, ifadeler birleştirilmiş ve bir "-" eklenir: .bc(a,(b,c))<-f<$>f r<$>(a,x)<-f r,(b,c)<-f x(a++b++"-",c)


1
f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
Kutuları

@Zgarb Teşekkürler! Bazı nedenlerden dolayı f(x:r)|x<'0',(a,(b,c))<-f<$>f r=(a++b++"-",c)|1<3=([x],r), her iki durumun da birleştirildiği bir sürüm aradığımda, bayt daha uzun olduğunu düşündüm.
Laikoni

5

Haskell, 54 bayt

v f""=""
v f(a:s)=last(v.v:[id|a>'-'])((a:).f)s
h=v h

İşlev vbir dize ve bir işlev alır, ilk alt ifadeyi yeniden düzenler, ardından her şey yeniden düzenlenene kadar işlevi dizenin geri kalanına uygular. Çağrı yığını ve işlev bağımsız değişkeni birlikte hangi ifadenin ayrıştırıldığını takip eder. İşlev hmeydan okumayı cevaplar ve sadece vkendisiyle birlikte kukla bir ilk argüman olarak adlandırılır.


1
Vaov! (1) Bu sadece 53, son satırsonu saymanıza gerek yok. (2) İlk satırı, v f l=likinci taşıdığınızda kısaltılabilir .
Ørjan Johansen

1
Birden fazla tüm ifadeyi ayrıştırmanız gerektiğini düşünmüyorum, böylece anonim işlevi kullanarak bir bayt kaydedebilirsiniz v id.
Ørjan Johansen

1
Aslında ilk satır hiçbir zaman geçerli girdi olarak çağrılmaz, böylece silebilirsiniz.
Ørjan Johansen

1
Muhafızlara ayrılmak lasthileyi bir bayt yeniyor gibi görünüyor .
Ørjan Johansen

4

Perl 5 , 57 bayt

sub f{"@_"=~s/x((?0)|.)((?0)|.)/my$n=$2;f($1).f($n).x/re}

Bunun xyerine operatör olarak kullanıyorum -(aşağıdaki TryItOnline bağlantısına bakınız).

Çevrimiçi deneyin!

Açıklamalar:
/x((?0)|.)((?0)|.)/ özyinelemeli olarak tam bir ifadeyi eşleştirir: a xbaşında, sonra bir ifade (?0)(yinelemeli çağrıdır) veya bir atom ( .), ardından başka bir ifade veya atom gelir.
Sonra ikinci ifade / atom ( my$n=$2;) kaydetmek gerekir çünkü aksi takdirde özyinelemeli aramalar geçersiz kılar.
İşlev daha sonra ilk ifadede ( f($1)), sonra ikincisinde özyinelemeli olarak çağrılır f($n)vex sonuna eklenir ( .x).


4

Piton 3, 117 112 105 100 98 76 62 61 59 bayt

def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]

Değişiklikler:

  • mümkünse kaldırılan satır aralıkları (-5 bayt)
  • tam işlev yerine lambda (-7 bayt, teşekkürler @Dada)
  • başka yok (-5 bayt, teşekkürler @Leaky Nun)
  • aşırı golfü geri al (-2 bayt, teşekkürler @Leaky Nun)
  • bunun yerine global bir liste üzerinde çalışın (-22 bayt)
  • aslında bunun yerine yineleyiciler üzerinde çalışalım (-14 bayt)
  • değiştirmek !=için >(-1 baytı, @ovs önerisinin kopyalanır)
  • tembel değerlendirme hilesi (-2 bayt, teşekkürler @ovs)

Şöyle kullanın:

>>> list(p(iter("--01-0-01")))
['0', '1', '-', '0', '0', '1', '-', '-', '-']


2
lambda x:p(x)[0]muhtemelen fişlevinizi değiştirebilir .
Dada

1
İhtiyacın yok else, methinks.
Leaky Nun

1
Baytları d="-"gerçekten kurtarıyor mu?
Sızdıran Rahibe

1
def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]59 bayt için
ovs

3

Pyth, 20 bayt

L+&-hbTsyM.-Btbytbhb

Bu bir işlev oluşturur y dizeyi parametre olarak bekleyen .

Çevrimiçi deneyin: Gösteri veya Test Paketi

Açıklama:

İşlev yayrıştırır ve ilk önek ifadesini bir postfix ifadesine dönüştürür. Yani, y"10"sadece geri dönecek gibi çağrılırsa 1.

L+&-hbTsyM.-Btbytbhb
L                      define a function y(b), that returns:
   -hbT                   remove the chars "10" from the first char b
                          (T=10, and - will convert a number to a string)
  &                       if this gives the empty string (a falsy value)
 +                hb         then append b[0] to it and return it
                             (so this will parse a digit 0 or 1 from the string)
  &                       otherwise (the first char is a -)
               ytb           parse the first prefix expression from b[1:]
                             (recursive call)
          .-Btb              remove this parsed expression bifurcated from b[1:]
                             this gives a tuple [b[1:], b[1:] without first expr]
        yM                   parse and convert an expression from each one
       s                     join the results
 +                hb         and append the b[0] (the minus) to it and return

2

Retina , 34 31 29 bayt


;
-;
¶
+`¶(.+);(.+)
$1$2-
;

Çevrimiçi deneyin!

;başlangıçta tek bir sayıdan oluşan ve daha sonra ayrıştırılmış olan her şeye büyüyen düğümleri belirtmek için kullanılır. -yeni satırlara dönüştürülür, böylece .+ayrıştırılmamış herhangi bir şeyi alabiliriz -.


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.