Dotty Strings auswerten

25

Schreiben Sie ein Programm, das eine Zeichenfolge mit ungerader Länge akzeptiert, die nur die Zeichen .und enthält :. Erstellen Sie mit Hilfe eines anfänglich leeren Stapels eine Zahl aus dieser Zeichenfolge wie folgt:

Für jedes Zeichen c in der Zeichenfolge (von links nach rechts) ...

  • Wenn c ist .und der Stapel weniger als 2 Elemente enthält, drücken Sie 1 auf den Stapel.
  • Wenn c ist .und der Stapel 2 oder mehr Elemente enthält, lassen Sie die beiden obersten Werte vom Stapel fallen und legen Sie ihre Summe auf den Stapel.
  • Wenn c ist :und der Stapel weniger als 2 Elemente enthält, drücken Sie 2 auf den Stapel.
  • Wenn c ist :und der Stapel 2 oder mehr Elemente enthält, lassen Sie die beiden obersten Werte vom Stapel fallen und schieben Sie ihr Produkt auf den Stapel.

Die resultierende Zahl ist der Wert oben im Stapel. Ihr Programm sollte diese Nummer auf stdout ausgeben (mit einem optionalen nachgestellten Zeilenumbruch).

(Eine kleine Analyse zeigt, dass immer nur eine Zahl übrig ist, es sei denn, die Zeichenfolge hat eine gerade Länge, weshalb wir diese ignorieren. Tatsächlich enthält der Stapel nie mehr als 2 Elemente.)

Zum Beispiel ist die Zahl für ::...:.:.9:

  2   1   2   2    /______ stack just after the character below is handled
2 2 4 4 5 5 7 7 9  \
: : . . . : . : .  <-- string, one character at a time

Zur Überprüfung der Gesundheit sind hier die Zahlen für alle Zeichenfolgen der Länge 1, 3 und 5:

. 1
: 2
... 2
..: 1
.:. 3
.:: 2
:.. 3
:.: 2
::. 4
::: 4
..... 3
....: 2
...:. 4
...:: 4
..:.. 2
..:.: 1
..::. 3
..::: 2
.:... 4
.:..: 3
.:.:. 5
.:.:: 6
.::.. 3
.::.: 2
.:::. 4
.:::: 4
:.... 4
:...: 3
:..:. 5
:..:: 6
:.:.. 3
:.:.: 2
:.::. 4
:.::: 4
::... 5
::..: 4
::.:. 6
::.:: 8
:::.. 5
:::.: 4
::::. 6
::::: 8

Das kürzeste Programm in Bytes gewinnt. Tiebreaker ist früherer Beitrag.

  • Sie können davon ausgehen, dass die Eingabe immer gültig ist, dh eine Zeichenfolge, die nur ungerade Werte enthält .und :deren Länge ungerade ist.
  • Anstatt ein Programm zu schreiben, können Sie eine Funktion schreiben, die eine gültige Zeichenfolge verwendet und die generierte Zahl ausgibt oder zurückgibt.
Calvins Hobbys
quelle
5
Bester minimalistischer Equalizer aller Zeiten.
dberm22

Antworten:

13

CJam, 27 24 23 22 Bytes

q{i]_,+~3<-"1+2* "=~}/

Ziemlich einfach. Ich benutze CJam's Stack als den in der Frage genannten Stack;)

Algorithmus

Schauen wir uns zuerst den ASCII-Code für .und an :.

'.i ':ied

[46 58]

Da in CJam Indexumbrüche durchgeführt werden, können Sie sehen, ob wir diese Werte direkt verwenden können, um die gewünschte Operation zu erhalten.

'.i4% ':i4%ed

[2 2]

Daher kann ich die ASCII-Codes nicht einfach in einer Operationszeichenfolge mit 4 Längen verwenden. Versuchen wir einige andere Werte

'.i 10% ':i 10%ed

[6 8]

was auf eine 4 länge schnur hinausläuft

[2 0]

Ich kann diese Mod 10-Operation verwenden, aber das kostet 2 Bytes. Versuchen wir etwas anderes

'.i5% ':i5%ed

[1 3]

Nice !, jetzt subtrahieren wir nur 1 für die Stapelgrößenbedingung, um die Indizes zu erhalten 0, 1, 2 and 3und ein 5Längenarray ( "1+2* ") als Schalterfall zu verwenden. Das letzte Leerzeichen ist nur ein Füllzeichen, um es auf Länge 5 zu bringen. Dies ist nur 1 zusätzliches Byte im Vergleich zur Modding-Operation.

q{                  }/    e# parse each input character in this loop
  i]                      e# convert '. or ': into ASCII code and wrap everything
                          e# in stack in an array
    _,+                   e# Copy the stack array, take its length and add the length to
                          e# the stack array 
       ~3<                e# unwrap the stack array and check if stack size is less than 3
                          e# 3 because either . or : is also on stack
          -               e# subtract 0 or 1 based on above condition from ASCII code
           "1+2* "        e# string containing the operation to perform
                  =~      e# chose the correct operation and evaluate it

Probieren Sie es hier online aus

Dank cosechy 1 Byte gespart

Optimierer
quelle
1
Wofür ist in der Abfolge der Operationen Platz?
Peter Taylor
@ PeterTaylor in der Post erklärt.
Optimierer
9

> <> (Fisch) , 33 Bytes

ib%1-i:1+?\~n;
5a*)?*+40.\b%1-0@i

Ziemlich einfach mit kleinen Tricks / Optimierungen.

Erläuterung:

  • Info: i= Codepunkt des nächsten Eingabezeichens, -1wenn das Ende der Eingabe erreicht ist; a= 10; b= 11; )=>
  • iCodepunkt des ersten Eingabezeichens,
  • b%1- top_of_stack mod 11 - 1Masken 48 ('.') , 56 (':')zu1 , 2
  • i:1+?\~n; Wenn das Ende der Eingabe erreicht ist, das letzte Ergebnis drucken und beenden
  • Andernfalls:
  • b%1- Maskeneingabe an 1 , 2
  • 0@ drücken 0unter die zwei nummern
  • i5a*) Lesen Sie die nächste Eingabe und maskieren Sie sie 0 , 1 Vergleich mit50
  • wenn 1(':' ) multipliziere die beiden obersten Elemente und erstelle einen Stapel [0 Produkt]
  • Fügen Sie immer die beiden obersten Elemente hinzu, um entweder [0 sum]oder einen Stapel zu erstellen[0+product=product]
  • 40.Sprung (Schleife) zurück zu Position (4,0), unserem Punkt 4,i:1+?\~n;
randomra
quelle
8

Haskell, 73 65 Bytes

Eine einfache Lösung, da der Stapel nie mehr als 2 Elemente enthält.

[x,y]#'.'=[x+y]
[x,y]#_=[x*y]
s#'.'=1:s
s#_=2:s
f=head.foldl(#)[]
Alephalpha
quelle
5

C 104 Bytes

k[2],n;f(char*c){for(n=0;*c;)k[n]=*c++-58?n>1?n=0,*k+k[1]:1:n>1?n=0,*k*k[1]:2,k[1]=n++?k[1]:0;return*k;}

Das ist zu lang.

BrainSteel
quelle
5

Pyth, 25 24 Bytes

eu?]?.xGHsGtG+GhHmqd\:zY

Ich habe eine Idee, als ich @ isaacgs Lösung studierte. Aber ich benutze einen Stapel.

Online-Demonstration oder Testsuite

Erläuterung

Als erstes konvertiere ich die Eingabezeichenfolge in 0s und 1s. A "."wird umgewandelt in a 0, a ":"in a 1.

mqd\:z   map each char d of input to (d == ":")

Dann reduziere ich diese Liste von Zahlen:

eu?]?.xGHsGtG+GhHmqd\:zY
 u                     Y   start with the empty stack G = []
                           for each H in (list of 0s and 1s), update G:
                              G = 
    ?.xGHsG                      product of G if H != 0 else sum of G
   ]                             wrapped in a list 
  ?        tG                 if G has more than 1 element else
             +GhH                G + (H + 1)
e                         take the top element of the stack
Jakube
quelle
4

JavaScript (ES6), 65

Wir verwenden nur 2 Zellen unseres Stapels.

Geben Sie einen Wert in s [0] ein.
Geben Sie dann an jeder ungeraden Position (von 0 an gezählt) in der Eingabezeichenfolge einen Wert in s [1] ein.
Führe an jeder geraden Position eine Berechnung aus (addiere oder multipliziere) und speichere das Ergebnis in s [0].

Vergessen Sie also den Stack und verwenden Sie nur 2 Variablen, a und b.

f=s=>[...s].map((c,i)=>(c=c>'.',i&1?b=1+c:i?c?a*=b:a+=b:a=1+c))|a

Ein schneller Test

for(i=0;i<128;i++)
{
  b=i.toString(2).replace(/./g,v=>'.:'[v]).slice(1)
  if(b.length&1) console.log(b,f(b))
} 

Ausgabe

"." 1
":" 2
"..." 2
"..:" 1
".:." 3
".::" 2
":.." 3
":.:" 2
"::." 4
":::" 4
"....." 3
"....:" 2
"...:." 4
"...::" 4
"..:.." 2
"..:.:" 1
"..::." 3
"..:::" 2
".:..." 4
".:..:" 3
".:.:." 5
".:.::" 6
".::.." 3
".::.:" 2
".:::." 4
".::::" 4
":...." 4
":...:" 3
":..:." 5
":..::" 6
":.:.." 3
":.:.:" 2
":.::." 4
":.:::" 4
"::..." 5
"::..:" 4
"::.:." 6
"::.::" 8
":::.." 5
":::.:" 4
"::::." 6
":::::" 8
edc65
quelle
-2:f=s=>[(c=s[i]>'.',i&1?b=1+c:+i?c?a*=b:a+=b:a=1+c)for(i in s)]|a
nderscore
@nderscore zumindest auf meinem borwser funktioniert das nicht. für (i in s) gibt zusätzliche Eigenschaften neben Indizes
edc65
es funktioniert für mich in Firefox 37.0.2. Versuchen Sie es in einem sauberen Browser-Tab. Es scheint, dass stackexchange Strings (in stub.en.js) zusätzliche Eigenschaften hinzufügt
nderscore
3

Pyth, 27 Bytes

Jmhqd\:zu?*GhHteH+GhHctJ2hJ

Ein Stapel? Wer braucht schon einen Stapel.

                       Implicit: z is the input string.
Jmhqd\:z               Transform the string into a list, 1 for . and 2 for :
                       Store it in J.
u            ctJ2hJ     Reduce over pairs of numbers in J, with the
                       first entry as initial value.
 ?    teH               Condition on whether the second number is 1 or 2.
  *GhH                  If 1, update running total to prior total times 1st num.
         +GhH           If 2, update running total to prior total plus 1nd num.

Demonstration.

isaacg
quelle
1
Genius. Und in der Zwischenzeit habe ich einen Stack (32 Bytes) implementiert. :-(
Jakube
3

Retina , 105 75 73 Bytes

Mein erstes Retina-Programm! (Vielen Dank an Martin Büttner für die Einsparung von 2 Bytes, ganz zu schweigen von der Erfindung der Sprache.)

Jede Zeile sollte in einer separaten Datei abgelegt werden. Oder Sie können sie alle in eine Datei einfügen und das -sFlag verwenden. Die <empty>Notation steht für eine leere Datei / Zeile.

^(a+;)?\.
$1a;
^(a+;)?:
$1aa;
;(a+;)\.
$1
(a+);aa;:
$1$1;
)`;a;:
;
;
<empty>
a
1

Inspiriert von der Antwort von mbomb007, verfolge ich jedoch einen etwas anderen Ansatz. Ein Hauptunterschied ist, dass ich den Stapel vor der dotty Schnur baue (mit der Oberseite des Stapels nach rechts zeigend). Dies macht es einfach, Symbole an Ort und Stelle in die entsprechenden Zahlen umzuwandeln. Ich benutze astattdessen auch 1, es nur am Ende auszutauschen, um zu vermeiden, Mehrdeutigkeiten in Sequenzen wie zu analysieren $1a. Wenn eine Antwort wie aaaaaaeine unäre Zahl akzeptabel ist, können die letzten beiden Zeilen / Dateien entfernt werden, um 4 Bytes zu sparen.

Erläuterung:

^(a+;)?\.
$1a;

Stimmt überein, wenn sich 0 oder 1 Elemente auf dem Stapel befinden ( (a+;)?), gefolgt von einem Punkt ( \.); In diesem Fall wird der Punkt durch ersetzt a;(dh es wird eine 1 gedrückt).

^(a+;)?:(.*)
$1aa;$2

Stimmt überein, wenn sich 0 oder 1 Elemente auf dem Stapel befinden, gefolgt von einem Doppelpunkt. In diesem Fall wird der Doppelpunkt durch ersetzt aa;(dh es wird eine 2 gedrückt).

;(a+;)\.
$1

Stimmt überein, wenn sich zwei Elemente auf dem Stapel befinden, gefolgt von einem Punkt. Löscht den Punkt und das Semikolon zwischen den Elementen und fügt sie hinzu.

(a+);aa;:
$1$1;

Stimmt überein, wenn der Stapel zwei Elemente enthält, von denen das oberste eine 2 ist, gefolgt von einem Doppelpunkt. Löscht den Doppelpunkt und die 2 und wiederholt die andere Zahl zweimal, wobei sie mit 2 multipliziert wird.

)`;a;:
;

Der reguläre Ausdruck stimmt überein, wenn sich zwei Elemente auf dem Stapel befinden, von denen das oberste eine 1 ist, gefolgt von einem Doppelpunkt. Löscht den Doppelpunkt und die 1 und lässt die andere Zahl unverändert (dh multipliziert mit 1).

)`zeigt das Ende einer Schleife an. Wenn Änderungen an der Zeichenfolge vorgenommen wurden, kehrt die Steuerung an den Anfang des Programms zurück und führt die Ersetzungen erneut aus. Wenn sich die Zeichenfolge nicht mehr ändert, haben wir alle Punkte und Doppelpunkte ersetzt, und alles, was übrig bleibt, ist die Bereinigung ...

;
<empty>

Löscht das verbleibende Semikolon.

a
1

Wandelt alle Einsen in Einsen um. Auch dieser Schritt ist nicht erforderlich, wenn Unärzahlen ein Symbol verwenden dürfen.

DLosc
quelle
Wird dann angenommen, dass der Beginn der Schleife die erste Datei ist?
mbomb007
@ mbomb007 Ja. Ich hatte das in den Dokumenten gesehen, aber vergessen, bis Martin mich daran erinnerte. ;)
DLosc
2

Rust, 170 Zeichen

fn f(s:String)->i32{let(mut a,mut b)=(-1,-1);for c in s.chars(){if b!=-1{a=match c{'.'=>a+b,':'=>a*b,_=>0};b=-1}else{b=match c{'.'=>1,':'=>2,_=>0};if a==-1{a=b;b=-1}};}a}

Mehr Beweis, dass Rust beim Golfen absolut schrecklich ist. Voller ungolfed Code:

#[test]
fn it_works() {
    assert_eq!(dotty_ungolfed("::...:.:.".to_string()), 9);
    assert_eq!(f("::...:.:.".to_string()), 9);
}

fn dotty_ungolfed(program: String) -> i32 {
    let (mut a, mut b) = (-1, -1);
    for ch in program.chars() {
        if b != -1 {
            a = match ch { '.' => a + b, ':' => a * b, _ => panic!() };
            b = -1;
        } else {
            b = match ch { '.' => 1, ':' => 2, _ => panic!() };
            if a == -1 { a = b; b = -1; }
        }
    }
    a
}

fn f(s:String)->i32{let(mut a,mut b)=(-1,-1);for c in s.chars(){if b!=-1{a=match c{'.'=>a+b,':'=>a*b,_=>0};b=-1}else{b=match c{'.'=>1,':'=>2,_=>0};if a==-1{a=b;b=-1}};}a}

Hier ist ein interessanter Trick, den ich in diesem verwendet habe. Sie können ein Zeichen in einer if / else-Anweisung abschneiden, indem Sie einen Wert zurückgeben, der sofort verworfen wird. Dies bedeutet, dass Sie nur ein Semikolon anstelle von zwei benötigen.

Beispielsweise,

if foo {
    a = 42;
} else {
    doSomething(b);
}

kann in geändert werden

if foo {
    a = 42
} else {
    doSomething(b)
};

Das spart ein Zeichen, indem ein Semikolon abgeschnitten wird.

Türknauf
quelle
2

Haskell, 88 81 79 Bytes

(h:t)![p,q]|h=='.'=t![p+q]|1<2=t![p*q]
(h:t)!s|h=='.'=t!(1:s)|1<2=t!(2:s)
_!s=s

Es scheint, dass mich jemand bei einer Haskell-Lösung bis an die Grenze geschlagen hat, nicht nur das, ihre Lösung ist kürzer als meine. Das ist schade, aber ich sehe keinen Grund, nicht zu posten, was ich mir ausgedacht habe.

Ankh-Morpork
quelle
2

APL (50)

Ich bin hier im Nachteil, weil APL keine Stack-basierte Sprache ist. Endlich musste ich die Reduzierung missbrauchen, um das Programm zu verkürzen.

{⊃{F←'.:'⍳⍺⋄2>⍴⍵:F,⍵⋄((⍎F⌷'+×')/2↑⍵),2↓⍵}/(⌽⍵),⊂⍬}

Die innere Funktion nimmt links einen 'Befehl' und rechts einen Stapel und wendet ihn an und gibt den Stapel zurück. Die äußere Funktion reduziert es über den String, beginnend mit einem leeren Stapel.

Erläuterung:

  • (⌽⍵),⊂⍬: die anfängliche Liste zu reduzieren. ⊂⍬ist eine leere Liste, die den Stapel darstellt,(⌽⍵) die Umkehrung der Eingabe. (Die Verkleinerung wird von rechts nach links über der Liste angewendet, sodass die Zeichenfolge von rechts nach links verarbeitet wird. Durch vorheriges Umkehren der Eingabe werden die Zeichen in der richtigen Reihenfolge angewendet.)

  • {...} : die innere Funktion. Es nimmt den Stapel rechts und ein Zeichen links und gibt den geänderten Stapel zurück.

    • F←'.:'⍳⍺: Der Index des Zeichens in der Zeichenfolge .: Je nach Wert ist dies 1 oder 2.
    • 2>⍴⍵:F,⍵: Wenn 2 größer als die aktuelle Stapelgröße ist, hängen Sie einfach den aktuellen Wert an den Stapel an.
    • : Andernfalls,
      • 2↓⍵: Entferne die beiden obersten Gegenstände vom Stapel
      • (... )/2↑⍵: Reduziere eine gegebene Funktion darüber und füge sie dem Stapel hinzu.
      • ⍎F⌷'+×': Die Funktion ist entweder +(Addition) oder ×(Multiplikation), ausgewählt mit F.
  • : Geben Sie schließlich das oberste Element auf dem Stapel zurück

Marinus
quelle
2

Ruby - 96 Zeichen

Das interessante Stück ist hier eval.

Abgesehen davon gehe ich davon aus, dass der Stapel nach dem ersten Zeichen immer 2, math, 2, math, ... ist. Dadurch kann ich weniger Code verwenden, indem ich zwei Zeichen gleichzeitig nehme - ich muss nie rechnen herausfinden, ob ein Zeichen Mathematik oder eine Zahl ist. Es ist positionell.

x,m=$<.getc>?.?2:1
(b,f=m.split //
b=b>?.?2:1
x=f ?eval("x#{f>?.??*:?+}b"):b)while m=gets(2)
p x

Ungolfed:

bottom_of_stack = $<.getc > '.' ? 2 : 1 # if the first char is ., 1, else 2
two_dots = nil
while two_dots = gets(2) do # get the next 2 chars
  number_char, math_char = two_dots.split //
  number = number_char > '.' ? 2 : 1
  if math_char
    math = math_char > '.' ? '*' : '+'
    # so bottom_of_stack = bottom_of_stack + number ...
    # or bottom_of_stack = bottom_of_stack * number
    bottom_of_stack = eval("bottom_of_stack #{math} number")
  else
    # if there's no math_char, it means that we're done and 
    # number is the top of the stack
    # we're going to print bottom_of_stack, so let's just assign it here
    bottom_of_stack = number
  end
end
p bottom_of_stack  # always a number, so no need for `puts`
Nicht dieser Charles
quelle
2

TI-BASIC, 78 73 70 69 66 Bytes

Input Str1
int(e^(1=inString(Str1,":
For(A,2,length(Str1),2
Ans+sum({Ans-2,1,1,0},inString("::..:",sub(Str1,A,2
End
Ans

TI-BASIC eignet sich gut für Einzeiler, da das Schließen von Klammern optional ist. Umgekehrt ist es eine schlechte Sprache, in der das Speichern mehrerer Werte erforderlich ist, da das Speichern in einer Variablen zwei bis vier Byte Speicherplatz beansprucht. Daher ist es das Ziel, so viel wie möglich in jede Zeile zu schreiben. TI-BASIC ist auch schrecklich (für eine Token-Sprache) bei der Manipulation von Strings jeglicher Art; Sogar das Lesen eines Teilstrings ist langwierig.

Tricks beinhalten:

  • int(e^([boolean]statt 1+(boolean; spart ein Byte
  • Teilsumme einer Liste anstelle von List Slicing (was das Speichern in einer Liste erfordern würde): Spart 3 Bytes
Lirtosiast
quelle
Sie sollten in Ordnung sein, Eingaben von Ans zu übernehmen ".:.":prgmDOTTYund beispielsweise 4 Bytes zu sparen.
MI Wright
@Wright Ich verwende Ans, um die Nummer auf dem Stapel zu speichern.
Lirtosiast
Ich meinte am Anfang - werde Linie 1 los und ändere die zweite Linie auf1+(":"=sub(Ans,1,1
MI Wright
1
Ich muss Str1 in der Schleife verwenden, in der Ans aufgenommen wird, damit ich nicht davonkomme, die Zeichenfolge in Ans zu belassen. Durch das Speichern in Str1 von Ans wird kein Speicherplatz gespart.
Lirtosiast
1

Gehen, 129 115 112 Bytes

func m(s string){a,b:=0,0;for c,r:=range s{c=int(r/58);if b>0{a=a*b*c+(a+b)*(c^1);b=0}else{b,a=a,c+1}};print(a)}

(etwas) ungolfed:

func m(s string){
    // Our "stack"
    a, b := 0, 0
    // abusing the index asignment for declaring c
    for c, r := range s {
        // Ascii : -> 58, we can now use bit fiddeling
        c = int(r / 58)
        if b > 0 {
            // if r is :, c will be 1 allowing a*b to pass through, c xor 1 will be 0
            // if r is ., c xor 1 will be 1 allowing a+b to pass through
            a = a*b*c + (a+b)*(c^1)
            b = 0
        } else {
            b, a = a, c+1 // Since we already know c is 0 or 1
        }
    }
    print(a)
}

Versuchen Sie es online hier: http://play.golang.org/p/B3GZonaG-y

Kristoffer Sall-Storgaard
quelle
1

Python 3, 74

x,*s=[1+(c>'.')for c in input()]
while s:a,b,*s=s;x=[x*a,x+a][-b]
print(x)

First transformiert die Eingabeliste in eine Folge von 1 und 2, wobei der erste Wert als Anfangswert verwendet wird x. sNehmen Sie dann von vorne zwei Elemente gleichzeitig ab , nehmen Sie die erste Zahl und addieren oder multiplizieren Sie sie mit der aktuellen Zahl, je nachdem, ob die zweite 1 oder 2 ist.

xnor
quelle
1

Nun, das ist so einfach, raffiniert von der OP (absichtlich)

es ist nur ...

Ausdruck in Klammern, der in eine postfixierte * / + Operation übersetzt wurde

Code: C (80 Byte)

int f(char*V){return*(V-1)?f(V-2)*(*V==58?*(V-1)/29:1)+(*V&4)/4**(V-1)/29:*V/29;}
  • Diese Funktion sollte vom Ende des Strings folgendermaßen aufgerufen werden: f (V + 10) wobei V = ".: ..:.: .. ::"

Eingang

Länge = 2n + 1 Vektor V vom Typ char '.' oder ':'

Ausgabe

eine ganze Zahl k

Funktion

  • k = (V [1] op (V [3]) V [2]) op (V [5]) V [4] ....

  • op (x): (x = '.') -> +, (x = ':') -> *


Simulation:

versuche es hier

Abr001am
quelle
Wie können Sie davon ausgehen, dass das Byte vor der Zeichenfolge ( *(V-1)) Null ist?
Nutki
wenn Sie einen neuen Vektor zuweisen, beginnt seinen Anfang immer vom leeren Segment, dessen Ende es IST ein leeres Zeichen
Abr001am
1

Retina, 181 135 129 Bytes

Jede Zeile sollte in einer separaten Datei sein. <empty>repräsentiert eine leere Datei. Die Ausgabe erfolgt in Unary.

^\..*
$&1;
^:.*
$&11;
^.
<empty>
(`^\..*
$&1
^:.*
$&11
^.(.*?1+;1+)
$1
^(\..*);(1+)
$1$2;
;1$
;
^(:.*?)(1+).*
$1$2$2;
)`^.(.*?1+;)
$1
;
<empty>

Wenn ${0}1verwendet, trennen sich die Klammern $0von der ersten passenden Gruppe 1, ansonsten wäre dies der Fall $01. Ich habe versucht, mit $001, aber dies scheint nicht in der .NET-Variante von Regex zu funktionieren.

Edit: Gefunden das $&ist das selbe wie$0 .

Im Pseudocode wäre dies im Wesentlichen eine do-while-Schleife, wie unten dargestellt. Ich drücke die erste Zahl, dann die Schleife: drücke die zweite Zahl, entferne die Operation (Anweisung), mache Mathe, entferne die Op. Wiederholen Sie die Schleife. Beachten Sie, dass beim Aufspringen einer Operation auch das Leerzeichen entfernt wird, nachdem alle Anweisungen ausgeführt wurden.

Kommentiert:

^\..*           # Push if .
$&1;
^:.*            # Push if :
$&11;
^.              # Pop op
<empty>


(`^\..*         # Loop, Push #
$&1
^:.*
$&11
^.(.*?1+;1+)    # Pop op
$1


^(\..*);(1+)    # Add if . (move ;)
$1$2;
;1$          # If mul by 1, remove
;
^(:.*?)(1+).*   # Mul if : (double)
$1$2$2;
)`^.(.*?1+;)    # Pop op, End Loop (clean up)
$1
;               # Remove semicolon
<empty>
mbomb007
quelle
Die Hauptsache, die ich golfmäßig sehe, sind Muster- / Ersatzpaare wie (:)(.*)-> $1$2, von denen ich mir ziemlich sicher bin, dass es nur (:.*)-> sein könnte $1(da Sie die beiden Gruppen in der gleichen Reihenfolge halten und nichts anderes mit ihnen machen) ).
DLosc
Ich wurde inspiriert und machte meine eigene Retina-Antwort. Vielen Dank, dass Sie mich dazu gebracht haben, diese interessante Sprache herunterzuladen!
DLosc
@ DLosc Cool! Ja, ich habe es noch nicht heruntergeladen. Ich habe einen Online-Regex-Ersatztester für jeden einzelnen Ersatz verwendet.
mbomb007
0

Python 3, 122 Bytes

x=input()
l=[0,0]
for _ in x:
 t=len(l)-2<2
 l=[[[0,0,l[-2]*l[-1]],l+[2]][t],[[0,0,sum(l)],l+[1]][t]][_=='.']
print(l[-1])

Ungolfed:

x = input()
l = []
for i in x:
    if i == '.':
        if len(l) < 2: 
            l+=[1]        #True, True = 1,1
        else:
            l=[sum(l)]    #True, True = 1,0
    else:
        if len(l)<2:
            l+=[2]        #False, True = 0,1
        else:
            l=[l[0]*l[1]] #False, False = 0,0
print (l[0])

In Python verweisen Sie auf den Index einer Liste wie folgt:

list[index]

Sie können einen booleschen Wert in das setzen, Trueist 1und Falseist 0.

# t is True if the length is less than 2, else false.

l=[ 

  # |------- Runs if char is : -------|
  # |------- l<2 -------| |- l>=2 -|

    [ [ 0,0, l[-2]*l[-1] ], l+[2] ] [t],

                                      # |---- Runs if char is . ----| 
                                      # |--- l<2 ---|  |- l>=2 -|

                                        [ [0,0, sum(l)], l+[1] ] [t] ]
                                                                      [_=='.']

Probieren Sie es hier online aus

Tim
quelle
0

Perl, 77 Bytes

@o=(0,'+','*');sub d{$_=shift;y/.:/12/;eval'('x s!\B(.)(.)!"$o[$2]$1)"!ge.$_}

erweitert:

@o=(0, '+', '*');
sub d{
    $_=shift;
    y/.:/12/;
    eval '(' x s!\B(.)(.)!"$o[$2]$1)"!ge.$_
}

Das @oArray ordnet den Operatoren Ziffern zu. Dann ersetzen wir Zahlenpaare durch den entsprechenden Operator, der nach infix geordnet ist. Der reguläre Ausdruck beginnt mit, \Bdaher stimmen wir nicht mit dem ersten Zeichen überein. Das Ergebnis vons///g sagt uns, wie viele offene Parens wir am Anfang brauchen. Wenn wir dann den vollständigen Infix-Ausdruck zusammengestellt haben, können wir ihn auswerten. (Löscheneval Sie, wenn Sie stattdessen den Ausdruck sehen möchten.)

Hier ist das Testkabel, mit dem ich die Ergebnisse verifiziert habe:

while(<>) {
    my ($a, $b) = m/(.*) (.*)/;
    print d($a), " $b\n";
}

Input ist die Liste der Dotty-Ausdrücke und ihrer Werte (in der Frage angegeben) und Output sind Paare von {actual, expected}.

Toby Speight
quelle