Özetle? Bu benim forte'm!


18

Giriş

Forte , sayıların değerlerini değiştirme kavramına dayanan çok tuhaf bir ezoterik dildir. Forte sayıları sabit değil, değişkenlerdir, LETbunlara yeni değerler atamak için bu komutu kullanabilirsiniz .

Örneğin, LET 2=4-1şu andan itibaren yürütüldükten sonra 2değeri değerini alır 3, yani değer 2bir ifadede her ortaya çıktığında bunun yerine "değiştirilir" 3. İfade (1+1)*2şimdi olarak değerlendirilecektir 9.

Forte'daki bu talimat hem bilgi depolamak hem de akış kontrolü için kullanılır (satırlar numaralandırılır ve sayılarının değerini değiştirerek yürütme sırasını belirleyebilirsiniz). Bu meydan okumada bu ikinci yönü ele almayacağız.

Meydan okuma

Forte LETifadelerinin basitleştirilmiş bir alt kümesi için bir tercüman yazmanız gerekir .

Bu dilbilgisini izleyen bir dizi satır girdi olarak alacaksınız:

<line>::= <number>=<expression>

<expression>::= <number>|<expression>+<number>

Not: bu dilbilgisi geçerli Forte değildir çünkü satır numaraları, LET ve parantezlerden yoksundur (her zaman zorunludur)

Yani, yalnızca hesaplama özetleriyle uğraşmanız ve sayılara değerler atamanız gerekir. Girdide parantez olmayacak ve her ifadenin soldan sağa değerlendirilmesi gerekecektir: kısmi sonuçların yeniden tanımlardan etkilendiğine dikkat edin!

Sayılar, dilinizin yerel tam sayı türünün sınırına (veya hangisi daha yüksekse) her zaman negatif olmayan tamsayılar olacaktır.

Her satır için, ifadenin sonucunu çıkarmalı ve bu sonucu, ilk satırın (muhtemelen yeniden atanmış) değerine atamalısınız; bu, aşağıdaki satırların nasıl yorumlanacağını etkiler.

Bu , en kısa kod (bayt cinsinden) kazanır!

Diğer kurallar

  • Girdi biçimi esnektir, örneğin satırsonu, dize listesi, sayı listesi içeren tek bir dize alabilirsiniz ... girdi.
  • Her satır için bir kez çağıran bir REPL ortamında çalıştırılacak bir işlev, tam bir program veya bir çözüm gönderebilirsiniz.
  • Standart boşluklar yasaktır, özellikle kodunuzda harici bir Forte yorumlayıcısını arayamazsınız.

Örnekler

Bunların hepsi aynı girdinin parçasıdır. Her satırdan sonra, o satıra göre beklenen çıktı, bazen ilgili yeniden atamaları gösteren bir yorum ile gösterilir (gerekli çıktının bir parçası değil).

5=4
4
6=5
4        # 5 -> 4
7=1+2+5
7
7=5+2+1
4        # Order of operations matters! 5+2 -> 4+2 -> 6 -> 4
18=5+6+7
12
5=3
3        # Remember: 5 -> 4
10=6+4
3        # 6 -> 4 -> 3, 3+3 = 6 -> 3

0geçerli bir sayı?
orlp

@orlp 0geçerlidir ("Sayılar her zaman negatif olmayan tamsayılar olacaktır")
Leo

Herhangi bir aritmetik işleç kabul etmeli miyiz?
bacchusbeale

@bacchusbeale Hayır, sadece özetleme.
Leo

Belirli bir maksimum sayı var mı, yoksa dilin yerel tamsayı türü kadar büyük mü? Ayrıca, bir sonuç listesi döndürmek geçersiz çıktı olur, değil mi? (hangi sayının hangi sayıya gittiği sözlük / haritayı yazdırmak gibi)
zgrep

Yanıtlar:


4

Jöle , 28 bayt

®y$ÐL
ṪÇ+Ç¥/Ṅ;®⁸Ǥ;©
⁸©ḷƓÇ€¤

Çevrimiçi deneyin!

Bu, standart girdiden girdi almanın ters olduğu birkaç Jelly programından biridir. Bu tam bir program (bir işlev yazmak daha kısa olurdu, ancak PPCG kuralları tarafından yasaklandı, çünkü ikinci kez düzgün çalışmayacaktı). Giriş biçimi şuna benzer:

[[5,[4]],[6,[5]],[7,[1,2,5]],[7,[5,2,1]],[18,[5,6,7]],[5,[3]],[10,[6,4]]]

açıklama

Yardımcı işlevi 1Ŀ (bir tamsayıyı değerine çevirir)

®y$ÐL
   ÐL   Repeatedly, until there are no further changes,
  $       apply the following unary function to {the input}:
 y          replace values using the mapping table
®             stored in the register.
        {Then return the eventual result.}

Daha ziyade, bu yardımcı işlev y, tanımlanmış olan yol nedeniyle tek bir değerde veya bir değer listesinde doğru şekilde çalışacaktır . Tek bir değer için birden fazla eşleme verilirse, ilk eşlemeyi tablodan alırız. Eşleme tablosu kayıt defterinde saklanır (temel olarak sadece bir değişkendir; Jelly'in sadece bir değişkeni vardır).

Yardımcı işlevi 2Ŀ (bir LET komutunu değerlendirin)

ṪÇ+Ç¥/Ṅ;®⁸Ǥ;©
Ṫ               On the last element of {the input},
 Ç              Run 1Ŀ,
     /          left fold it via
    ¥             the following binary function:
  +                 add {the two arguments}
   Ç                and run 1Ŀ on {the result},
      Ṅ         write {the result} (and a newline) to standard output,
       ;®       append the value of the register,
            ;   prepend
           ¤      the following value:
         ⁸          {the input, without its last element}
          Ç         with 1Ŀ run on it
             ©  and store that value in the register {and return it}.

Gerçekten burada bir dönüş değeri istemiyoruz; bunu sadece yan etkileri için çalıştırıyoruz (kaydı güncellemek ve atanan değeri çıkarmak). Jöle işlevleri her zaman bir değer döndürür, bu yüzden eşleme tablosunun geri dönmesine izin veririz, çünkü bu en tersidir.

Ana program

⁸©ḷƓÇ€¤
 ©       Initialize the mapping table
⁸        with the empty string (which is also the empty list)
  ḷ      then evaluate and discard
      ¤  the following value:
   Ɠ       a line from standard input, parsed into a data structure
    Ç€     with each element transformed via 2Ŀ
         {and leave the empty string to be printed implicitly}

Normalde, bu bağlamda çalıştırıldığında bize ilk komut satırı argümanını verir, ancak bir tane yoktur (standart girişten girdi alıyoruz), bu yüzden bize null dizesini veren alternatif bir modda çalışır. Kaydı başlatma gereksinimi (varsayılan değeri olan 0ve çöküyor y), kullanıcının girdisini dolaylı olarak anlatamayacağımız anlamına gelir, yani onu standart girişten ( Ɠ) bir komut satırı argümanı ( ³veya ) ve alternatif kullanımına erişebilmek , alışılmadık (Jelly için) giriş biçiminin aslında bir bayt daha kısa olduğu anlamına gelir.

Bu geliştirilebilir olabilir. İkinci satır ihtiyaçları söylemek neden hala çözemedim ⁸Ǥ;yerine sadece daha ;@Çiki eşdeğer olmalıdır Ben Jöle anladığım kadarıyla kullanılması eksikliği göz önüne alındığında, bildiğim kadarıyla, - µ/ ð/ ø- nedense ama ikincisi çöker. Benzer şekilde, bayt kaybetmeden programı yeniden düzenlemenin başka yolları da vardır, bu yüzden işleri biraz daha kısaltmanın bir yolunu kaçırmış olabilirim.

Bu arada, son satırda değiştirmek ;, programın iç işleyişine ilginç bir görünüm kazandırır, çünkü daha sonra dönüş değerlerinin dolaylı olarak çıktısını alan "kayıt geçmişini" çıktılar 2Ḷ.


5

Perl 5 , 92 bayt

90 bayt kod + -plbayrak.

sub f{($b=$h{$a=pop}//$a)!=$a?f($b):$a}s%(\d+)\+(\d+)%f($1)+f$2%e&&redo;/=/;$_=$h{f$`}=f$'

Çevrimiçi deneyin!

%hSayıları arasındaki eşlemeyi saklamak için hashtable'ı kullanıyorum .
Function ( sub) f, giriş eşlemesinin (veya hiçbir sayı ile eşlenmemişse girişinin ) döndürdüğü sayıyı döndürür: girişin eşlendiği sayıyı $h{$a=pop}alır. Yoksa, //$adeğeri ($b=$h{$a=pop}//$a), input ( $a) olur. Bu değerlerin, sonsuz döngü ( !=$a) için girişin kendisi olmadığından emin oluruz . Daha sonra, fgirdiyi yinelemeli olarak arar veya döndürürüz.
Ana program iki adımdan oluşur:
- s%(\d+)\+(\d+)%f($1)+f$2%e&&redosağ taraftaki ilk eklemeyi değerlendirirken, hala bir ekleme var: x+ydeğerlendirmenin sonucu ile değiştirilir f(x)+f(y).
- /=/;$_=$h{f$`}=f$'ödevi yapar:/=/ile sol tarafa $`ve sağ tarafa ile erişim sağlar $', sonra $h{f$`}=f$'ödevi yapar. Ve bunu $_her satırdan sonra örtük olarak yazdırılana da atarız .


5

JavaScript (Node.js) , 81 bayt

v=x=>(v[x]=v[x]||x,v[x]-x?v(v[x]):x)
f=x=>l=>v[v(x)]=l.reduce((p,x)=>v(v(x)+p),0)

Çevrimiçi deneyin!

Atanacak değerle f'yi çağırarak, ardından da birlikte eklenecek bir değer dizisiyle sonucu çağırarak girdiyi alır. (ie f(5)([4])) Birden fazla satır için tekrarlayın.

vbir sayının gerçek geçerli değerini hesaplamak için bir işlev olarak ve gerçek değerleri depolamak için bir nesne olarak kullanılır. Öncelikle v[x]=v[x]||xbunun v[x]tanımlanmasını sağlar. v[x]-xbunun gerçek sayı olup olmadığını belirlemek için bir karşılaştırma yapar. Sayı kendisiyle v(v[x])eşleşmezse, tekrar tekrar dener, aksi takdirde geri döner x.

f ikinci çağrının hesaplanan değeri döndürdüğü bir bayt kaydetmek için kıvrılmış hesaplama ve atamayı gerçekleştirir.


3

Haskell , 11611310610 bayt

(#)=until=<<((==)=<<)
e?((n,s):r)|m<-foldl1(\a b->e#(e#a+e#b))s=m:(\x->last$m:[e#x|x/=e#n])?r
e?r=[]
(id?)

Çevrimiçi deneyin! Her denklem 4=3+1+5tuple olarak gösterilir (4,[3,1,5]). Anonim işlev (id?)bu tür grupların bir listesini alır ve tüm ara sonuçların bir listesini döndürür.

#verilen bir fonksiyonun ebir başlangıç noktasını ve başlangıç ​​değerini bulma fonksiyonudur x.

Fonksiyon ?bir değerlendirme fonksiyonu alır eve her denklemi özyinelemeli olarak çözer. foldl1(\a b->e#(e#a+e#b))sbir denklemin sağ tarafını değerlendirir ve sonucu kaydeder miçin, örneğin 4=3+1+5bu hesaplar eval(eval(eval 3 + eval 1) + eval 5)her yerde, evalbir düzeltme noktası uygulamasıdır e. Sonra eval işlevi yeni görevi almaya değiştirilir n: hesaba (\x->last$m:[e#x|x/=e#n])aynıdır \x -> if x == eval n then m else eval x.

İlk değerlendirme işlevi, idher bir tamsayıyı kendine eşleyen işlevdir .


Daha kısa bir düzeltme noktası fonksiyonu için Ørjan Johansen sayesinde 2 bayt tasarruf!


İyi iş! Bu arada, tüm ara sonuçları iade etmeniz gerekiyor, böylece düşebilirsinizlast.
Leo

2
(#)e=until((==)=<<e)eveya (#)=until=<<((==)=<<)daha kısadır.
Ørjan Johansen

@ ØrjanJohansen Çok teşekkürler!
Laikoni

3

Tamam, 48 bayt

a:[];s:{*(a@x;x)^0N}/;f:{a[s@x]:y:{s@x+y}/s'y;y}

Kullanımı: f[5;1 2 3] / 5=1+2+3

Çevrimiçi deneyin!


Yalnızca sayı kullanmak gibi kullanabileceğiniz sayılar için bir üst sınırın olması sakıncası yoksa 0 içinden 998, sonra aşağıdaki yeterli ( 41 bayt birkaç maksimum bağlı ±):

a:!999;s:(a@)/;f:{a[s@x]:y:{s@x+y}/s'y;y}

Açıklama:

; üç tanımı birbirinden ayırır.

asözlük / sayıların haritasıdır. İlk durumda, gerçek, boş bir sözlük[] ikinci durumda bunun numaralarının listesi, 0için 998.

ssayı verildiğinde "sonuç" numarasını bulan bir işlevdir. /Çıktı değişen durana kadar kendi çıkışa kendisini uygulanacaktır fonksiyon araçlarının ucunda.

Son bit, fşu anlama gelir:

f:{                      } /function called f, input number x, list y
                    s'y    /apply s to every number in the list
                   /       /fold through the list
            {s@x+y}        /    sum the two numbers, apply s
   a[s@x]:                 /set the s(x) to map to the final sum
          y:           ;y  /redefine y to be the final sum, then return it

3

Python 3, 146 132 130 bayt

@Dada sayesinde 14 bayt kaydedildi
@ mbomb007 sayesinde 2 bayt kaydedildi

d={}
g=lambda x:d.get(x)and x!=d[x]and g(d[x])or x
def f(t):
 for n,(s,*r)in t:
  for b in r:s=g(g(s)+g(b))
  d[g(n)]=s;yield g(n)

Çevrimiçi deneyin!

Girdiyi denklem tuplesi olarak alır [ x = y + z + was (x, (y, z, w))], çıktı üreteci üzerinden.


Test edilebilmesi için bir çağırma örneği gösterebilir misiniz?
Leo

1
@Leo TIO ekledi.
Uriel

1
gmuhtemelen yazılabilirdi g=lambda x:d.get(x)and d[x]!=x and g(d[x])or x. Ve sanırım 2 yerine girintilemek için 1 boşluk kullanabilirsiniz. Bu [132 bayt] 'a ulaşmanızı sağlayacaktır ( Çevrimiçi deneyin! ).
Dada

1
@Dada teşekkürler! çok kötü yarı boşluk girintileri yok: P
Uriel

1
Yarım boşluk girintisi yok, ancak başka bir düzgün numara iki boşluk yerine tek bir sekme kullanıyor. Girintiler farklı olduğu sürece, Python mutludur (örneğin ek iç içe düzeylerde girintiler olarak boşluk sekmesi ve sekme boşluğu kullanabilirsiniz). Bu size iki bayt kurtarabilir :)
Leo
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.