99 için bir tercüman yazın


99

99 ("doksan dokuz" olarak telaffuz edilir) yepyeni bir Ezoterik programlama dilidir ( 99 ile karıştırılmamalıdır , italik yazıya dikkat edin). Buradaki göreviniz, 99 için mümkün olduğunca kısa bir tercüman yazmak . En az bayt olan gönderim kazanır. Tiebreaker ilk gönderilenlere gider.

Bu soru her zamankinden biraz daha derin olduğundan ve iyi cevaplar görmeye istekli olduğum için en sevdiğim cevaba 250 rep ödül vereceğim (mutlaka kazanan değil).

99 Spec

99 bir olan zorunlu dili. 99 programındaki her satır tek bir ifadedir ve yürütme sırasında, komut göstericisi en üst satırdan başlar ve sonraki satırların her birini sırayla izleyerek yol boyunca yürütür. Program, son satır çalıştırıldığında sona erer. Goto ifadeleri, talimat göstergesinin yolunu yeniden yönlendirebilir.

Newline, boşluk ve 99 programda 9önemli olan sadece üç karakter . Diğer tüm karakterler tamamen göz ardı edilir. Ek olarak, her satırdaki izleyen boşluklar yoksayılır ve bir satırdaki birden çok boşluk bir boşluk olarak okunur. ("Newline", herhangi bir ortak satır sonu kodlamasını ifade eder . Tercümanınızın hangisini kullandığı önemli değildir.)

Yani bu program:

   9      BLAH        99   9a9bb9c9
9 this line and the next have 6 trailing spaces 9      
      

Bu programla aynı mı:

 9 99 9999
9 9

Değişkenler

99'daki değişkenlerin tümü bir veya daha fazla 9dizilmiş ( 9+regex cinsinden) isimlere sahiptir . Örneğin 9, 99ve 9999999999tüm farklı değişkenlerdir. Doğal olarak, sınırsız sayıda var (hafıza kısıtlamalarını kısıtlayan).

Her değişkenin değeri imzalı, keyfi bir tamsayıdır. Varsayılan olarak, her değişken kendi sayısal temsiline atanır. Bu nedenle, yeniden atanmamışsa, değişkenin değeri 99, değişkenin değeri ise 9999, vb. Olur. Değişkenlere açıkça atanana kadar düz sayılar gibi davrandığını düşünebilirsiniz.

VAşağıda rastgele bir değişken adına başvurmak için kullanacağım .
Her örneği Vile değiştirilmesi mümkündür 9, 99, 999, 9999, vb

tablolar

99'da beş farklı ifade türü vardır . 99 programdaki her satır tam olarak bir deyim içerir.

Burada açıklanan sözdizimi, tüm yabancı karakterlerin kaldırıldığını, tüm izleyen boşlukların kaldırıldığını ve çoklu boşlukların tüm dizilerinin tek boşluklarla değiştirildiğini varsayar.

1. işlem yok


Boş bir satır no-op'tur . Hiçbir şey yapmaz (talimat göstergesini arttırmanın yanı sıra).

2. Çıkış

V

Satırdaki tek bir değişken Vbu değişkeni stdout'a yazdırır.

VTek sayıda 9( 9, 999vb.) Varsa , V9'a bölünen tam sayı değeri (ondalık olarak) yazdırılır.

Eğer Vçift ​​sayıları 9( 99, 9999vb.) Varsa , 9'a bölünmüş kodlu ASCII karakteri Vmod 128 basılacaktır. (Bu (V / 9) % 128, 0 ila 127 arasında bir değerdir.)

Örnek : Program

9
9999

yazdırırdı 1W. İlk satır 19/9 1 olduğundan yazdırıyor . İkinci satır W9999/9 1111 ve 1111 mod 128 87, 87 87 ise karakter kodudur W.

Satır sonlarının çıktı belirteçleri arasında yazdırılmadığını unutmayın. \nSatır sonu için açıkça yazdırılması gerekir.

3. Giriş

 V

Önde boşluğu olanV bir satırdaki tek bir değişken , stdin'den girdi alır ve onu bu değişkende saklar.

VTek sayıda varsa , 9kullanıcı işaretli bir tamsayıyı yazabilir ve Vbu değerin 9 katına ayarlanır.

VÇift sayıları varsa , 9kullanıcı herhangi bir ASCII karakterini yazabilir Vve karakter kodunun 9 katına ayarlanır.

Örnek : Verilen -57ve Agirdi olarak, bu program

 9
9
 99
99

çıktı -57A. Dahili olarak, değişken 9-513 değerine ve 99585 değerine sahip olacaktır.

Tercümanınız, girişlerin her zaman sözdizimsel olarak geçerli olduğunu varsayabilir.

4. Atama

Bu ifade keyfi olarak uzun olabilir. Satırda boşluklarla ayrılmış iki veya daha fazla değişken var:

V1 V2 V3 V4 V5 ...

Bu, tüm endekslere sahip olanların toplamına eksi olarak eksi tek endekslere sahip olanların toplamına atar (hariç ). Atamalar referans değil değere göredir.V1VVV1

Çoğu dile çevrilebilir .V1 = V2 - V3 + V4 - V5 + ...

Yani, sadece iki değişken varsa, bu normal bir atamadır:

V1 V2V1 = V2

Üç tane varsa, o zaman çıkarma:

V1 V2 V3V1 = V2 - V3

Ve +/ -sign her bir ek değişkenle ileri geri geçiş yapmaya devam ediyor:

V1 V2 V3 V4V1 = V2 - V3 + V4

Örnek : Bu program şöyle olur 1110123:

999           Prints triple-nine divided by nine (111).
999 9 9       Assigns triple-nine to zero (nine minus nine).
999           Prints triple-nine divided by nine (0)
9 999 9       Assigns single-nine to negative nine (zero minus nine).
999 999 9     Adds nine to triple-nine (really subtracts negative nine).
999           Prints triple-nine divided by nine (1).
999 999 9     Adds nine to triple-nine (really subtracts negative nine).
999           Prints triple-nine divided by nine (2).
999 999 9     Adds nine to triple-nine (really subtracts negative nine).
999           Prints triple-nine divided by nine (3).

5. Goto (eğer sıfırsa zıpla)

Bu ifade ayrıca keyfi bir şekilde uzun olabilir. Bu, boşluk ile ayrılan bir çizgi, iki veya daha fazla değişken olduğu bir lider alanı :

 V1 V2 V3 V4 V5 ...

Yanındaki değerlerin bazıları sıfır değil ise, o zaman no-op gibi davranır. Komut işaretçisi her zamanki gibi bir sonraki satıra taşınır.V1

Eğer bütün değerlerin yanı sıra olan sıfır, o zaman kullanıcı işaretçi dizi hat taşınır . Satırlar sıfır dizinlidir, yani sıfırsa, işaretçi üst satıra gider. Olumsuz veya mümkün olan en yüksek endeksten daha büyükse program (normalde hatasız) sona erer ( satır eksi bir satır).V1 V1V1V1

Not Burada 9 bölü değildi. Ve bir değişkenin 9'un katı olmadığı bir değer olması imkansız olduğundan, yalnızca 9'un katı olan satır sayıları atlanabilir.V1

Örnekler:

Bu program 1sonsuza dek yazacaktır:

9          Prints single-nine divided by nine (always 1).
99 9 9     Assigns double-nine to zero.
 99 99     Jumps to line zero (top line) if double-nine is zero.

Bu program

99999999                                              Print G.
999 99                                                Set triple-nine to ninety-nine.
9999999999 9999999999 9999999999 99 99 9 9 999 999    Set 10-nine to zero.
99999999999 9999999999                                Set 11-nine to zero.





999                                                   Print triple-nine's value divided by nine. (This is the ninth line.)
99999999                                              Print G.
999 999 9                                             Subtract nine from triple-nine.
 99999 999                                            Jump to line 5-nines if triple-nine is zero (ends program).
 9 99999999999 9999999999                             Jump to line nine if 10-nine and 11-nine are zero (always jumps).

11'den 1'e kadar olan sayıları azalan sırayla, G'ile çevrili olarak çıkarır:

G11G10G9G8G7G6G5G4G3G2G1G

ek detaylar

İdeal tercüman, 99 program dosya ismi ile komut satırından bağımsız değişken olarak çalışacaktır . G / Ç ayrıca komut satırında anında yapılır.

Bununla birlikte, programda bir dize gibi giriş belirteçlerinin bir listesini (örneğin ["-57", "A"]) alan bir tercüman işlevi yazabilirsiniz . İşlev, çıkış dizesini yazdırmalı veya döndürmelidir.

Tercüman çalıştırmanın ve G / Ç işlemlerini kullanmanın biraz farklı yolları, bu seçenekler sizin dilinizde imkansızsa.


Bonus: 99'da havalı bir şeyler yazın ve memnuniyetle bu yazıya bir örnek olarak koyacağım.


Umarım 99. meydan okumamdan zevk aldın ! : D


9
Ben upvoting kabul ancak mevcut skor ... 9
wchargin

30
@WChargin şimdi 99'unu almaya çalışmanız gerekecek gibi görünüyor
trlkly

5
Şüphesiz Kendi kendine barındırma (a yazmak için ikramiyesi var 99 yılında tercüman 99 ), hayır?
Gabe

5
@Gabe Buna benzer bir cevap muhtemelen ödül alırdı, ancak tek cevap bu olsaydı, tercümanı ne yorumlardı? ;)
Calvin'in Hobileri

1
Çalışır @Optimizer: pastebin.com/raw.php?i=h73q58FN
coredump

Yanıtlar:


16

CJam, 157 bayt

{:I;_N" 9"+--N/:P:,$W=){1a*Ab}%:V;{PT):T(=:LS%_{LS#\:,_,({(\{V=}%@{V-1@{2$*+0@-\}*\;t:V;}{:|T@V=9*?:T;}?}{~\{_V=\1&!{128%c}*o}{VIW):W=it:V;}?}?}R?Tg)TP,<*}g}

Çevrimiçi deneyin:

açıklama

Bunu doğru girintili ve yorumlarla biçimlendirmeye çalışmak muhtemelen sonsuza dek sürecek, bu yüzden algoritmik bir özet vereceğim.

Kod bir bloktur, CJam'ın anonim işlevlere analogudur. Blok, program dizesini ve çalıştırıldığında yığındaki girdilerin listesini bekler.

Başlatma üç adımdan oluşur. İlk olarak, giriş listesi kaydedilir. Ardından, programdaki anlamlı olmayan her karakter kaldırılır ve sonuç bir satır listesine bölünür ve kaydedilir. Son olarak, değişken listesi başlatıldı. Bu liste, ad uzunluğu ile indekslenen her değişkeni 9'a bölünmüş değerine eşler (bir değişken hiçbir zaman 9'un katı olmayan bir değeri tutamaz ve bu değişiklikten elde edilenler hariç tüm işlemler). Liste, en uzun satırın uzunluğuna kadar başlatılır; bu, mevcut en uzun değişken adda bir üst sınırdır. Ayrıca başlangıç ​​değişken değerlerinden dolayı bir miktar örtük başlatma var: satır numarası 0 ve giriş dizini -1.

Tercüman beklendiği gibi uygulanır: bir sonraki satırı okuyan, satır numarasını artıran ve satır numarası mevcut bir satırı işaret ederken satırı yürüten bir döngü. Satır ayrıştırma önce satırın boş olmadığını kontrol eder, ardından aritenin 1 veya> 1 olmasına bağlı olarak dallar, daha sonra baştaki bir alan olup olmadığına göre dallar. Bu dört şube, dört (no-op hariç) operasyonu, her şey gibi agresif bir şekilde golf oynamasına rağmen, çoğunlukla basit bir şekilde taklit eder. Notun belki de bir optimizasyonu, geçerli bir giriş dizisinin her zaman program tarafından beklenen türde bir öğe üretmesi gerektiğinden, değişken adının uzunluğuna bağlı olarak giriş için ayrı durumlar vermemem gerektiğidir. Giriş listesinden okunan öğenin beklenen tipte olduğu varsayılır.


15
+1. Oldukça kısa. Şimdi, bir CJam tercüman yazabilirim 99 ? ;-)
coredump 10.05 te

9
@coredump *
Runer112 16.03

Kahretsin, sadece 195 alabilirim ve sonra umudumu kaybettim ve pes ettim: P
Optimizer

Negatif değerler yazdırırken bu doğru modulo almaz. Bu urun, sabitlenebilir 128%ile 128,=.
Martin Ender

26

Python 3, 421 414 410 404 388 395 401 bayt

golfed:

import sys,re
v,i,c,g,L={},0,[re.sub('( ?)[^9]+','\\1',l).rstrip().split(' ')for l in open(sys.argv[1])],lambda i:v.get(i,int(i)//9),len
while-1<i<L(c):
 d=c[i];l=L(d);e,*f=d;i+=1
 if l>1:
  x,*y=f
  if e:w=list(map(g,f));v[e]=sum(w[::2])-sum(w[1::2])
  elif l==2:j=input();v[x]=int(j)if L(x)%2 else ord(j)
  elif~-any(g(j)for j in y):i=g(x)*9
 elif e:w=g(e);print(w if L(e)%2 else chr(w%128),end='')

Ungolfed:

import sys, re

# Intialise variable table.
vars_ = {}
get_var = lambda i: vars_.get(i, int(i)//9)

# Parse commands.
commands=[re.sub('( ?)[^9]+','\\1',l).rstrip().split(' ') for l in open(sys.argv[1])]

# Run until the current instruction index is out of bounds.
index=0
while 0 <= index < len(commands):
    # Get the current command and increment the index.
    command = commands[index]
    l = len(command)
    first = command[0]
    index += 1

    if l > 1:
        # Handle the "assignment" command.
        if first:
            operands = [get_var(i) for i in command[1:]]
            vars_[first] = sum(operands[0::2]) - sum(operands[1::2])
        # Handle the "input" command.
        elif l==2:
            inp = input()
            vars_[command[1]] = int(inp) if len(command[1]) % 2 else ord(inp)
        # Handle the "goto" command.
        elif not any(get_var(i) for i in command[2:]):
            index = get_var(command[1]) * 9
    # Handle the "output" command.
    elif first:
        val = get_var(first)
        print(val if len(first) % 2 else chr(val % 128),end='')

Neredeyse spec'in tam anlamıyla bir uygulaması, bulabildiğim kadarıyla golf oynadım.

Tek bağımsız değişken olarak 99 kaynak kodlu bir dosya sağlayarak komut satırından çalıştırın (örneğin OP'deki son örnek):

> python3 ninetynine.py countdown.txt
G11G10G9G8G7G6G5G4G3G2G1G
>

Ek bir avantaj olarak, burada "99 şişe" bir (daha doğrusu fakir) uygulaması var 99 : http://pastebin.com/nczmzkFs


1
@DLosc: ilk konunuzla ilgili: Ben de elsebir sayıdan sonra çıkarılabileceğini düşünmüştüm, fakat daha önce denediğimde bir sözdizimi hatası aldım. Diğer ipuçlarınız olsa çok takdir!
Mac

3
@ coredump: Spesifikasyonun yazıldığı şekilde, her değişken daima dokuz ile bölünebilen bir değere sahip olacaktır. Değişkenlerin herhangi bir değeri almasına izin vermek ve gerektiğinde sadece dokuz ile çarpmak / bölmek (özellikle gotorutinde ve değişkenin varsayılan değerini alırken) daha özlü buldum . Dilin kullanıcısı söz konusu olduğunda, farketmez.
Mac

2
elseKendisi değil , sadece önündeki boşluk. Örn 3*n+1if n%2else n//2.
DLosc

1
@DLosc: üzgünüm, yanlış konuştum - Gerçekten de boş alan demek istedim else. Örneğin, ben yerine çalıştı print(w if L(e)%2 else chr(w%128))ile print(w if L(e)%2else chr(w%128))ve bir sözdizimi istisna var.
Mac

1
Tek - ideone.com adresinde test ettim ve işe yaradı, ancak haklısınız, gerçek Python3 tercümanında (Ubuntu'da 3.4.0) çalışmıyor. Bu ipuçlarını açıklığa kavuşturur: Alfabetik bir jetondan sonra gelen bir sayı genel olarak çalışır, ancak veya ile başlayan jetonlar için değil (ve yorumlardan hiçbiri için değildir) . eE0or
DLosc

16

Common Lisp, 1180 857 837 836 bayt

Bunun kazanmayacağını biliyorum, ama bunu golf oynarken çok eğlendim. CJam'da yazılmış iki 99'dan fazla tercüman olan 343 baytı kaldırmayı başardım.

Ayrıca, oldukça eğlenceli bir şekilde, onu sıkıştırmaya ne kadar çok çalışırsam, o kadar çok Common Lisp için, kodu derlemeye yorumlamaktan çok daha kısa olduğu konusunda ikna oldum .

(defmacro g(g &aux a(~ -1)> d x q(m 0)r v(n t)c(w 0)? u z)(flet((w(n p)(intern(format()"~a~a"p n))))(#1=tagbody %(case(setf c(ignore-errors(elt g(incf ~))))(#\  #2=(when(> w 0)(pushnew w v)(if u()(setq ?(oddp w)))(#5=push(w w'V)u)(setf w 0))(setf z t))(#\9(incf w)(setf >(or >(and n z))z()n()))((#\Newline())#2#(#5#(when u(setf u(reverse u)a(pop u))(if >(if u`(when(every'zerop(list,@u))(setf @,a)(go ^))`(setf,a,(if ?'(read)'(char-code(read-char)))))(if u`(setf,a,(do(p m)((not u)`(-(+,@p),@m))(#5#(pop u)p)(#5#(if u(pop u)0)m)))`(princ,(if ? a`(code-char(mod,a 128)))))))r)(incf m)(setf ?()u()z()>()n t)))(if c(go %))$(decf m)(setq d(pop r))(if d(#5# d x))(when(=(mod m 9)0)(#5#(w #3=(/ m 9)'L)x)(#5#`(,#3#(go,(w #3#'L)))q))(if(>= m 0)(go $)))`(let(@,@(mapcar(lambda(n)`(,(w n'V),(/(1-(expt 10 n))9)))v))(#1#,@x(go >)^(case @,@q)>))))
  • Sözlüksel analiz ve kod oluşturma araya sokulur: İçsel gösterimi saklamıyorum, ancak her bir satırı doğrudan işlerim.
  • tagbody2 döngü gerçekleştirmek için bir tane var :

     (... (tagbody % ... (go %) $ ... (go $)) result)
    
  • yerel değişkenler &aux

  • bir kapatma işlemi değil, doğrudan yorumlanmış kod
  • vb.

Ungolfed, yorum yaptı

(defmacro parse-99
    (string &aux
              (~ -1) ; current position in string
              a      ; first variable in a line 
              >      ; does current line starts with a leading space?
              d      ; holds a statement during code generation
              x      ; all statements (labels + expressions)
              q      ; all generated case statements 
              (m 0)  ; count program lines (first increases, then decreases) 
              r      ; list of parsed expressions (without labels)
              v      ; set of variables in program, as integers: 999 is 3
              (n t)  ; are we in a new line without having read a variable? 
              c      ; current char in string 
              (w 0)  ; currently parsed variable, as integer 
              ?      ; is first variable odd? 
              u      ; list of variables in current line, as integers
              z)     ; is the last read token a space?
  (flet((w(n p)
          ;; produce symbols for 99 variables
          ;; e.g. (10 'V) => 'V10
          ;;      (4 'L)  => 'L4
          (intern(format()"~a~a"p n))))
    (tagbody
     parse
       (case (setf c
                   ;; read current char in string,
                   ;; which can be NIL if out-of-bounds
                   (ignore-errors(aref string (incf ~))))

         ;; Space character
         (#\Space
          #2=(when(> w 0)
               (pushnew w v)            ; we were parsing a variable, add it to "v"
               (if u()(setq ?(oddp w))) ; if stack is empty, this is the first variable, determine if odd
               (push(w w'V)u)           ; add to stack of statement variable
               (setf w 0))              ; reset w for next variable

          ;; Space can either be significant (beginning of line,
          ;; preceding a variable), or not. We don't know yet.
          (setf z t))

         ;; Nine
         (#\9
          (incf w) ; increment count of nines
          (setf >(or >(and n z)) ; there is an indent if we were
                                 ; starting a newline and reading a
                                 ; space up to this variable (or if we
                                 ; already know that there is an
                                 ; indent in current line).
                ;; reset z and n
                z()n()))

         ;; Newline, or end of string
         ((#\Newline())
          #2#  ;; COPY-PASTE the above (when(> w 0)...) statement,
               ;; which adds previously read variable if necessary.

          ;; We can now convert the currently read line.
          ;; We push either NIL or a statement into variable R.

          (push(when u
                     (setf u (reverse u) ; we pushed, we must reverse
                           a (pop u))    ; a is the first element, u is popped
                     (if >
                         ;; STARTS WITH LEADING SPACE
                         (if u
                             ;; JUMP
                             `(when(every'zerop(list,@u))(setf @,a)(go ^))

                             ;; READ
                             `(setf,a,(if ?'(read)'(char-code(read-char)))))

                         ;; STARTS WITH VARIABLE
                         (if u

                             ;; ARITHMETIC
                             `(setf,a,(do(p m) ; declare p (plus) and m (minus) lists

                                         ;; stopping condition: u is empty
                                         ((not u)
                                          ;; returned value: (- (+ ....) ....)
                                          `(-(+,@p),@m))

                                        ;; alternatively push
                                        ;; variables in p and m, while
                                        ;; popping u

                                        (push(pop u)p)

                                        ;; first pop must succeed, but
                                        ;; not necessarly the second
                                        ;; one.  using a zero when u
                                        ;; is empty covers a lot of
                                        ;; corner cases.

                                        (push(if u (pop u) 0) m)))

                             ;; PRINT
                             `(princ,(if ? a`(code-char(mod,a 128)))))))
               r)
          ;; increase line count
          (incf m)
          ;; reset intermediate variables
          (setf ?()u()z()>()n t)))

       ;; loop until end of string
       (if c (go parse))


     build
       ;;; Now, we can add labels in generated code, for jumps

       ;; decrease line count M, which guards our second loop
       (decf m)

       ;; Take generated statement from R
       (setq d(pop r))

       ;; we pop from R and push in X, which means X will eventually
       ;; be in the correct sequence order. Here, we can safely
       ;; discard NIL statements.

       ;; We first push the expression, and THEN the label, so that
       ;; the label ends up being BEFORE the corresponding statement.
       (if d(push d x))

       ;; We can only jump into lines multiple of 9
       (when (=(mod m 9)0)
         ;; Push label
         (push(w #3=(/ m 9)'L)x)
         ;; Also, build a case statement for the jump table (e.g. 2(go L2))
         (push`(,#3#(go,(w #3#'L)))q))
       ;; loop
       (if(>= m 0)(go build)))

    ;; Finally, return the code
    `(let(@ ; target of a jump instruction

          ;; other variables: V3 represents 999 and has a default value of 111
          ,@(mapcar(lambda(n)`(,(w n'V),(/(1-(expt 10 n))9)))v))

       ;; build a tagbody, inject statements from X and case statements from Q
       ;; label ^ points to jump table : we go to ^ each time there is a JUMP
       ;; label > is the end of program

       ;; note that if the case does not match any authorized target
       ;; address, we simply end the programs.
       (tagbody,@x(go >)^(case @,@q)>))))

Değerlendirme sırasında standart girdi / çıktıları kullanırız, yani standart readve princişlevleri kullanırız. Dolayısıyla, ortaya çıkan kod, aşağıda gösterildiği gibi komut satırında yürütülebilir hale getirilebilir.

99 program çalıştırılırken girdiler tamamen iyi durumda değildir : kullanıcının ne tür değerler beklendiğini bildiği varsayılmaktadır.

Tek olası çalışma zamanı ek yükü, atlama sırasında ortaya çıkabilir, çünkü bir değişkenin değerini değerlendirmemiz ve bu değeri bir etiketle eşleştirmemiz gerekir. Bunun dışında tercüman oldukça verimli olacaktır.

Mac'ten her seferinde 9'a bölmek ve çarpmak zorunda olmadığımız akıllıca gözlemlere dayanarak , mevcut sürüm yürütme sırasında hiçbir zaman 9'u bölmemeyi veya 9 ile çarpmamayı yönetiyor .

Örnek

Biz değiştirirseniz defmacrotarafından defun, biz oluşturulan kodu görüyoruz. Örneğin:

(g
"99999999                                              Print G.
999 99                                                Set triple-nine to ninety-nine.
9999999999 9999999999 9999999999 99 99 9 9 999 999    Set 10-nine to zero.
99999999999 9999999999                                Set 11-nine to zero.





999                                                   Print triple-nine's value divided by nine. (This is the ninth line.)
99999999                                              Print G.
999 999 9                                             Subtract nine from triple-nine.
 99999 999                                            Jump to line 5-nines if triple-nine is zero (endsprogram).
 9 99999999999 9999999999                             Jump to line nine if 10-nine and 11-nine are zero (alwa

")

İşte sonuç kodu:

(LET (@
      (V5 11111)
      (V11 11111111111)
      (V1 1)
      (V10 1111111111)
      (V2 11)
      (V3 111)
      (V8 11111111))
  (TAGBODY
   L0
    (PRINC (CODE-CHAR (MOD V8 128)))
    (SETF V3 (- (+ V2) 0))
    (SETF V10 (- (+ V3 V1 V2 V10) V3 V1 V2 V10))
    (SETF V11 (- (+ V10) 0))
   L1
    (PRINC V3)
    (PRINC (CODE-CHAR (MOD V8 128)))
    (SETF V3 (- (+ V3) V1))
    (WHEN (EVERY 'ZEROP (LIST V3)) (SETF @ V5) (GO ^))
    (WHEN (EVERY 'ZEROP (LIST V11 V10)) (SETF @ V1) (GO ^))
    (GO >)
   ^
    (CASE @ (0 (GO L0)) (1 (GO L1)))
   >))

Yürütüldüğünde, "G11G10G9G8G7G6G5G4G3G2G1G" yazdırıyor

Komut satırı

Bir çekirdek dökerek ve toplevelişlevi belirterek bir yürütülebilir dosya oluşturabiliriz . Adlı bir dosya tanımlayın boot.lispsen nereye koyduğunu defmacrove sonra aşağıdaki bilgileri:

(defun main()(parse-99 <PROGRAM>))
(save-lisp-and-die "test-99" :executable t :toplevel #'main)

Çalışan sbcl --load boot.lispaşağıdaki çıktıyı verir:

$ sbcl --load boot.lisp 
This is SBCL 1.2.8.32-18c2392, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
[undoing binding stack and other enclosing state... done]
[saving current Lisp image into test-99:
writing 5824 bytes from the read-only space at 0x20000000
writing 3120 bytes from the static space at 0x20100000
writing 55771136 bytes from the dynamic space at 0x1000000000
done]

Ardından, derlenmiş 99 programı çalıştırarak :

$ time ./test-99
G11G10G9G8G7G6G5G4G3G2G1G
real    0m0.009s
user    0m0.008s
sys     0m0.000s

99 şişe

Eğer ilgileniyorsanız, burada yazılan 99 şişe program için derlenmiş koddur Mac'in cevap : http://pastebin.com/ZXe839CZ (bu eski elimizdeki sürümüdür jmpve endetiketler, bir çevreleyen lambda ve güzel aritmetik).

İşte hala çalıştığını kanıtlamak için yeni sürümde bir uygulama: http://pastebin.com/raw.php?i=h73q58FN


6

TI-84 Basic (Hesaplama Komut Dosyası), 376 373 377 381 byte

Bir TI-84 hesap makinesinde çalışıyorsa, standart bir testte kullanabileceksiniz ... bu yüzden yararlıdır;)

Minimum işletim sistemi sürümü - toplama sigma nedeniyle 2.53MP (MathPrint)

#Get input from STDIN
:Ans+":"->Str0
#Initialize instruction pointer
:1->I
#Initialize variable set
:DelVar L1999->dim(L1
#Strip out those pesky non-newline/space/9 characters
:For(J,1,length(Ans
:sub(Str0,J,1
:If not(inString(": 9",Ans
:sub(Str0,1,J-1)+sub(Str0,J+1,length(Str0)-J->Str0
:End
#Main interpreting loop
:While I<length(Str0
:sub(Str0,I+1,inString(Str0,":",I+1)-I-1->Str1
:DelVar A" "=sub(Ans,1,1->A
:inString(Str0,":",I+1->I
:If A
:sub(Str1,2,length(Str1)-1->Str1
:End
:length(Str1->L
#0 is Output, 1 is Input, 2 is Assignment, 3 is Goto
:2A+inString(Str1," ->B
:If not(Ans
:Disp L1(L
:If Ans=1
:Then
:Input C
:C->L1(L
:End
#Get those delimited variables
:If B>1
:Then
:"{"+Str1->Str2
:While inString(Ans," 
:inString(Ans," 
:sub(Str2,1,Ans-1)+sub(Str2,Ans+1,length(Str2)-Ans->Str2
:End
:log(expr(Ans)+1->L2
:End
:If B=2
#Gotta expand that -+ pattern
:Ans(2->L1(Ans(1
;Love that summation Σ
:If B=3 and Σ(L2(K),K,2,dim(L2
:Then
:DelVar IFor(K,0,9L2(1
:inString(Str0,":",I+1->I
:End
:End

PS ASCII yönergeleri tam olarak izlenemedi, ancak TI-Basic'te :yeni bir satır. Bu nedenle, koddaki tüm yeni satırlar , her satırın başında :veya #başında gerekli olmadıkları anlamına gelir . Başlangıç ​​belirteçleri :ve #yorumlar ve kod arasında sadece ayırt.

Orijinal Hex Dump (376 Bayt)

49 3f bb 54 5d 20 39 39 39 04 b5 5d 20 3f 72 04 aa 09 3f d3 4a 2b 31 2b bb 2b 72 3f bb 0c aa 09 2b 4a 2b 31 3f ce b8 bb 0f 2a 3e 29 39 2a 2b 72 3f bb 0c aa 09 2b 31 2b 4a 71 31 11 70 bb 0c aa 09 2b 4a 70 31 2b 72 71 4a 04 aa 09 3f d4 3f d1 49 6b bb 2b aa 09 3f bb 0c aa 09 2b 49 70 31 2b bb 0f aa 09 2b 2a 3e 2a 2b 49 70 31 11 71 49 71 31 04 aa 20 3f bb 54 41 2a 29 2a 6a bb 0c 72 2b 31 2b 31 04 41 3f bb 0f aa 09 2b 2a 3e 2a 2b 49 70 31 04 49 3f ce 41 3f bb 0c aa 20 2b 32 2b bb 2b aa 20 11 71 31 04 aa 20 3f d4 3f bb 2b aa 20 04 4c 3f 32 41 70 bb 0f aa 20 2b 2a 29 04 42 3f ce b8 72 3f de 5d 20 10 4c 11 83 39 3f ce 72 6a 31 3f cf 3f dc 43 3f 39 43 04 5d 20 10 4c 3f d4 3f ce 42 6c 31 3f cf 3f 2a 08 2a 70 aa 20 04 aa 01 3f d1 bb 0f 72 2b 2a 29 3f bb 0f 72 2b 2a 29 3f bb 0c aa 01 2b 31 2b 72 71 31 11 70 bb 0c aa 01 2b 72 70 31 2b bb 2b aa 01 11 71 72 04 aa 01 3f d4 3f c0 bb 2a 72 11 70 31 04 5d 01 3f d4 3f ce 42 6a 32 3f 72 10 32 04 5d 20 10 72 10 31 3f ce 42 6a 33 40 ef 33 5d 01 10 4b 11 2b 4b 2b 32 2b b5 5d 01 3f cf 3f bb 54 49 d3 4b 2b 30 2b 5d 01 10 31 3f bb 0f aa 09 2b 2a 3e 2a 2b 49 70 31 04 49 3f d4 3f d4 2e 76

Düzenleme # 1 - Mac'in gözlemini kullanarak optimize edilmiş 3 bayt Düzenleme # 2 & # 3 - Runer112 tarafından tespit edilen sabit hatalar.


11
Standartlaştırılmış testler gibi stresli durumlarda kullanımı kolay olmak, tam olarak 99 için tasarladım .
Calvin'in Hobileri

1
#Yorumlar için farklı bir karakter kullanmanızı önerebilir miyim ? (Not: Asıl koddaki yorumlar, sadece Ans'ı gizleyen ve kapatılmamış bir dizgenin bulunduğu bir çizgi olarak uygulanır)
Riking

8
Aslında bunu çalıştırmayı denedin mi? Bilmedim, ama sadece biraz daha bakmaktan, en az yarım düzine böcek gibi görünen şeyleri gördüm. Örneğin: değişkenler kendi değerleri ile başlatılmadı, Ansgiriş üzerine yazıldı, böylece Ans->Str06. satırda hata oluşacak, bir sub()komutun uzunluk argümanının sıfır olabileceği birden çok örnek var, Ans11 satırında bir hata oluşacak Böylece Ans-Jhata olacak ... Ve ben sadece programın ilk yarısına baktım.
Runer112

1
@Timtech Bu, yine de, diğer sorunları bırakıyor. Bahsettiğim gibi, karakter G / Ç eksikliği, değişken başlatma eksikliği ve bir sub()komutun sıfır uzunluğa sahip olabileceği ve hata atabileceği birden fazla örnek var. Ve sub()istekler sabitlendikten sonra, korkarım daha fazla sorun ortaya çıkarabilir.
Runer112

1
@Timtech I buna atıfta bulunuyordu: "Varsayılan olarak, her değişken kendi sayısal temsiline atanır. Bu nedenle, atanmamışsa, değişkenin değeri 99, değişkenin değeri ise 9999, ve bunun gibi." Ve 0 uzunluğu uzunlukları, benzer yollarla üretilebilir "", ancak bu, temelde hiçbir dizi manipülasyon komutunun, dahil olmak üzere boş bir dize tüketemeyeceği veya üretemeyeceği bir tür hatadır sub().
Runer112

5

C 426 458 481 497

Düzenle Belki de çok uzağa gidiyorum, ancak bu Visual C: fopen ve getc için FILE * yerine int kullanarak, stdio.h Visual C ile çalışıyor.

Düzenle 2 Yeniden düzenle yürütme adımı, daha fazla karmaşa, 32 karakter kaydedildi

B[99999],*r,*i[9999],V[999],v,w,m,n;unsigned p,s;
main(b,a)char*a[];{r=i[0]=B;m=fopen(a[1],"r");
do if(w=getc(m),n+=w==57,w<33){
if(n){for(v=1,b=n;--b;)v=v*10+1;V[n]=v;*r++=p?-n:n;b=n=0;};
w-32?(*r=p=0,b=i[++s]=++r):(p=b,b=0);}while(w>=0);
while(p<s)if(w=0,r=i[p++],v=*r++)
if(m=v>0,*r){for(;b=*r++;m=-m)w=w+m*V[b]|!m*V[b];m?V[v]=w:(p=w?p:9*V[-v]);
}else~v&1?!m?V[-v]=getchar():putchar(V[v]&127):m?printf("%d",V[v]):scanf("%d",V-v);
}

Bağımsız konsol programı, komut satırından alınan program adı ve konsol üzerinden giriş / çıkış.

Eski stil K&R, global değişkenler ve parametreler için varsayılan int türü. EOF'yi -1 olarak kabul edersek (bildiğim her C uygulamasında olduğu gibi)

Visual Studio 2010 uyarılarıyla derler (Win32 konsolu C ++ projesi, C olarak derlenir) Ideone'da derlenir, ancak bir dosyaya ihtiyaç duyduğu için çalıştırılamaz.

İlk adım, kaynak kod okunur ve ayrıştırılır, her satır 9'luk sayılara dayalı bir tamsayı dizisi olarak saklanır. Boş bir satır varsa, ilk sayı negatiftir. Yani: 9 BLAH 99 9a9bb9c9( 9 99 9999) olur -1,2,4 Bir kısayol var - o kadar yasal değil: '' den küçük tüm kodlar yeni satırlar olarak kabul edilir.

Bu adımda, kullanılan tüm değişken önceden başlatılmıştır.

Uygulama adımı, 9 numaraya bölünen saklama numaralarını kaydetme, fırfırlar olmadan özellikleri izler.

Daha okunabilir aynı kod (umarım), boşluklar ve yeni satırlar eklenir

B[99999],*r,*i[9999],V[999],v,w,m,n;
unsigned p,s;
main(b,a)char*a[];
{
  r=i[0]=B;
  m=fopen(a[1],"r");
  do if(w=getc(m),n+=w==57,w<33)
  {
     if(n){for(v=1,b=n;--b;)v=v*10+1;V[n]=v;*r++=p?-n:n;b=n=0;};
     w-32?(*r=p=0,b=i[++s]=++r):(p=b,b=0);
  }
  while (w>=0);
  while (p<s)
    if (w = 0, r = i[p++], v = *r++)
        if (m = v > 0, *r){
            for(; b = *r++; m = -m)
                w = w + m*V[b] | !m*V[b];
            m ? V[v]=w : (p = w ? p : 9*V[-v]);
        } else
            ~v & 1 
            ? !m ? V[-v] = getchar() : putchar(V[v] & 127)  
            : m ? printf("%d", V[v]) : scanf("%d", V - v);
}

1
Ayrıca GCC 4.8.2 ile çalışır. C99 olarak derler!
EMBLEM

4

Haskell, 550 bayt

import Data.List.Split
import System.Environment
a#b=takeWhile(/=a)b
(!)=map
main=do(f:_)<-getArgs;readFile f>>=e.(p!).lines
p l=(if ' '#l<'9'#l then[0]else[])++length!(wordsBy(/='9')l)
e l=(\x->div(10^x-1)9)%l where
 _%[]=return()
 v%([]:r)=v%r
 v%([n]:r)=putStr(if odd n then show(v n)else[toEnum$v n`mod`128])>>v%r
 v%([0,n]:r)=do i<-getLine;u n(if odd n then read i else fromEnum$head i)v%r
 v%((0:n:m):r)|any(/=0)(v!m)=v%r|v n<0=v%[]|1<2=v%drop(9*v n)l
 v%((n:m):r)=u n(sum$zipWith(*)(v!m)(cycle[1,-1]))v%r
u n i v= \x->if x==n then i else v x

Örnek, dosyada depolanan "geri sayım" programı ile çalıştırılır i.99

$ ./99 i.99
G11G10G9G8G7G6G5G4G3G2G1G

Ungolfed versiyonu:

import Data.List.Split
import System.Environment

-- The main function takes the first command line argument as a file name,
-- reads the content, splits it into lines, parses each line and evaluates
-- the list of parsed lines.
main = do
 (f:_)<-getArgs
 readFile f >>= eval.map parse.lines

-- each line is coverted into a list of integers, which represent the number
-- of 9s (e.g. "999 99 9999" -> [3,2,4]). If there's a space before the first
-- 9, a 0 is put in front of the list (e.g. " 9 9 999" -> [0,1,1,3]).
parse l = (if takeWhile (/=' ') l < takeWhile (/='9') l then [0] else [])
   ++ map length (wordsBy(/='9') l)

-- The work is done by the helper function 'go', which takes two arguments
--   a) a functions which takes an integer i and returns the value of the
--      variable with i 9s (e.g: input: 4, output: value of 9999). To be
--      exact, the value divided by 9 is returned.
--   b) a list of lines to work on
-- 'eval' starts the process with a function that returns i 1s for every i and
-- the list of the parsed input. 'go' checks which statement has to be
-- executed for the next line and calls itself recursively
eval list = go (\x -> div (10^x-1) 9) list
   where
   go _ []                  = return ()
   go v ([]:r)              = go v r
   go v ([n]:r)             = putStr (if odd n then show(v n) else [toEnum (v n`mod`128)]) >> go v r
   go v ([0,n]:r)           = do i<-getLine ; go (update n (if odd n then read i else fromEnum$head i) v) r
   go v ((0:n:m):r)
      | any (/=0) (map v m) = go v r
      | v n < 0             = go v []
      | otherwise           = go v (drop (9*v n) list)
   go v ((n:m):r)           = go (update n (sum $ zipWith (*) (map v m) (cycle[1,-1])) v) r

-- updates a function for retrieving variable values.
-- n = position to update
-- i = new value
-- v = the function to update
update n i v = \x->if x==n then i else v x

4

JavaScript (ES6) 340 352

2 parametreli bir fonksiyon

  • çok satırlı bir dizge olarak program kodu
  • dizi olarak giriş

Üçüncü isteğe bağlı parametre (varsayılan 10k) maksimum yineleme sayısıdır - Sonsuza dek süren bir programı sevmiyorum

JSFiddle Test etmek

I=(c,i,k=1e5,
  V=v=>v in V?V[v]:v/9 // variable getter with default initial value
)=>(c=>{
 for(p=o='';--k&&p<c[L='length'];)
   (v=(r=c[p++].split(' '))[S='shift']())? // no leading space
      r[r.map(t=>w-=(m=-m)*V(t),w=0,m=1),0]?V[v]=w // Assign
      :o+=v[L]&1?V(v):String.fromCharCode(V(v)&127) // Output
   : // else, leading space
    (v=r[S]())&&
       (r[0]?r.some(t=>V(t))?0:p=9*V(v) // Goto
       :(t=i[S](),V[v]=v[L]&1?t:t.charCodeAt()) // Input
    )
})(c.replace(/ (?=[^9])|[^9\s]/g,'').split('\n'))  // code cleaning
||o

4

q / k, 490 469

M:mod;T:trim;R:read0;S:set;s:" "
f:(rtrim')(f:R -1!`$.z.x 0)inter\:"9 \n"
k)m:{@[x;&M[!#x;2];-:]}
b:{}
k)p:{1@$$[1=M[#x;2];(K x)%9;"c"$M[(K x)%9;128]];}
k)i:{S[(`$T x);$[1=M[#T x;2];9*"J"$R 0;*9*"i"$R 0]]}
k)K:{$[#!:a:`$x;.:a;"I"$x]}
k)v:{(S).(`$*:;+/m@K'1_)@\:T's\:x}
k)g:{$[&/0=C:K'c:1_J:s\:T x;n::-1+K@*J;|/~0=C;;(d<0)|(d:*C)<#f;exit 0]}
k)r:{`b`p`i`v`g@*&(&/x=s;q&1=c;(e~s)&1=C;(q:e~"9")&1<c:#s\:x;((e:*x)~s)&1<C:#s\:1_x)}
k)n:0;while[~n>#o:(r')f;(o n)f n;n+:1]
\\

.

$ q 99.q countdown.txt -q
G11G10G9G8G7G6G5G4G3G2G1G

Komut, q ve k'nin bir karışımıdır, bu yüzden ilk önce k işlevlerinde birden çok kez kullanmak istediğim birkaç q anahtar sözcüğünü tanımlarım. (temel olarak # makroları tanımla)

M:mod;T:trim;R:read0;S:set

f programa iletilen dosyayı okur ve gereksiz karakterleri çıkarır

q)f
"99999999"
"999 99"
"9999999999 9999999999 9999999999 99 99 9 9 999 999"
"99999999999 9999999999"
""
""
""
""
""
"999"
"99999999"
"999 999 9"
" 99999 999"
" 9 99999999999 9999999999"

m bir liste / vektör alır ve tek indeksleri -1 ile çarpar

q)m 1 2 3 4 5
1 -2 3 -4 5

b no op-op hatları için kullanılan sadece boş bir fonksiyondur

p yazdırma işlevidir.

Kbir değişkeni inceleyen bir işlevdir. Eğer değişken varsa, onu döndürür, aksi halde sadece değişmezi döndürür.

//999 not defined, so just return 999
q)K "999"
999
//Set 999 to 9
q)v "999 9"
//K now returns 9
q)K "999"
9

v atama işlevidir.

g goto işlevidir.

r bir dize alır ve hangi işlemin uygulanması gerektiğine karar verir.

Ve nihayet, sadece yineleyici olarak, fdizgiler listesini nyineliyorum. Goto fonksiyonu ngerektiği gibi güncellenecektir .


3

Perl, 273 266 255 244 238

Netlik için satır sonları eklendi.

open A,pop;
for(@c=<A>){
y/ 9//cd;s/ +/ /g;s/ $//;
$p="((99)+|9+)";$a='+';
s/^ $p$/$1='$2'?ord<>:<>/;
s/^$p$/print'$2'?chr$1%128:$1/;
s/^ $p /\$_=$1*011unless/&&y/ /|/;
s/ /=/;s/ /$a=-$a/ge;
s!9+!${x.$&}=$&/9;"\$x$&"!eg}
eval$c[$_++]until/-/|$_>@c

Komut satırından alınan program adı:

$ perl 99.pl 99beers.99

Programın her satırı örneğin Perl koduna dönüştürülür:

print'$x99'?chr$x99999999%128:$x99999999
$x999=$x99
$x9999999999=$x9999999999-$x9999999999+$x99-$x99+$x9-$x9+$x999-$x999
$x99999999999=$x9999999999





print''?chr$x999%128:$x999
print'$x99'?chr$x99999999%128:$x99999999
$x999=$x999-$x9
$_=$x99999*011unless$x999
$_=$x9*011unless$x99999999999|$x9999999999

Daha fazla detay

open A,pop; # open the source file
for(@c=<A>){ # read all lines into @c and iterate over them
y/ 9//cd; # remove all but spaces and 9's
s/ +/ /g;s/ $//; # remove duplicate and trailing spaces
$p="((99)+|9+)";$a='+';
s/^ $p$/$1='$2'?ord<>:<>/; # convert input
s/^$p$/print'$2'?chr$1%128:$1/; # convert output
s/^ $p /\$_=$1*011unless/&&y/ /|/; # convert goto
s/ /=/;s/ /$a=-$a/ge; # convert assignment
s!9+!${x.$&}=$&/9;"\$x$&"!eg} # initialize and convert variables
eval$c[$_++]until/-/|$_>@c # run (program counter is in $_)
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.