Bewerten Sie eine Kette von Ungleichungen

17

Schreiben Sie Code, um zu bewerten, ob eine Kette von Ungleichungen wahr oder falsch ist. Eine Beispieleingabe ist die Zeichenfolge

3<=4!=9>3==3

Dies ist wahr, weil jede seiner Komponenten wahr ist:

(3<=4) and (4!=9) and (9>3) and (3==3)

Eingang:

Eine Zeichenfolge, die eine Kette aus einer oder mehreren Ungleichungen darstellt. Die zulässigen Vergleichsoperatoren sind

==   equals
!=   does not equal
>    is greater than
>=   is greater than or equal to
<    is less than
<=   is less than or equal to

Die zulässigen Zahlen sind einstellige Zahlen 0bis 9. Es werden keine Leerzeichen, Klammern oder andere Symbole angezeigt.

Ausgabe:

Die Richtigkeit der Ungleichung als konsistenter Wahrheits- oder Falschwert . Konsistent bedeutet, dass jede Ausgabe von Truthy gleich ist und jede Ausgabe von Falsey gleich ist.

Beschränkung:

Ziel dieser Herausforderung ist es, Code zu schreiben, der die Ungleichungen verarbeitet, anstatt sie als Code auszuwerten, selbst für eine einzelne Ungleichung in der Kette. Aus diesem Grund sind Methoden wie Python's evalund solche, execdie Code auswerten oder ausführen, verboten. Dies gilt auch für Funktionen, die eine Methode oder einen Operator als Zeichenfolge nachschlagen. Es ist auch nicht gestattet, Prozesse oder Programme zu starten, um die Evaluierung für Sie durchzuführen.

Testfälle:

3<=4!=9>3==3
True

3<=4!=4
False

5>5
False

8==8<9>0!=2>=1
True
xnor
quelle
Können wir Eingaben mit Unicode-Ungleichungszeichen wie ≤ und ≥ anstelle von <= und> = akzeptieren?
FUZxxl
@FUZxxl Das kannst du nicht.
Xnor

Antworten:

7

Rubin, 71 + 1 = 72

-nFühren Sie mit dem Befehlszeilenflag aus

p (0..99).none?{|i|~/#{a=i%10}(#{%w/!=|. <?=* >?=*/[a<=>b=i/10]})#{b}/}

Generiert alle möglichen fehlgeschlagenen regulären Ausdrücke und überprüft, ob die Eingabezeichenfolge mit einer von ihnen übereinstimmt. Ausgänge, truewenn keine, sonst false. Übernimmt die Eingabe über STDIN, getrennt durch Zeilenumbrüche.

Tricks:

  • Wir erhalten alle möglichen Ziffernpaare durch Schleifen von 0 bis 99 und Extrahieren der Ziffern 10s und 1s.
  • Der einzige tatsächliche Vergleich, den wir durchführen, ist a<=>b, der -1,0 oder 1 für kleiner, gleich oder größer zurückgibt. Diese werden auf verschiedene Elemente eines Arrays mit drei Zeichenfolgen aufgeteilt und finden den regulären Ausdruck für Vergleiche, die nicht übereinstimmen.
Histokrat
quelle
Was für eine clevere Strategie!
Xnor
6

Perl, 82

$_=<>;($'<=>$&)-61+ord$1&&($2&&$&==$')^('$'lt$1)&&die"\n"while/\d(.)(=?)/g;print 1

Gibt 1 aus, wenn true, und eine leere Zeile, wenn false, da die leere Zeichenfolge Perls Haupt-Falsey-Wert ist.

Die while-Schleife geht über die Zeichenfolge, die dem regulären Ausdruck entspricht \d(.)(=?). Dann entsprechen die Variablen $1und $2den Zeichen des Operators und die Sondervariablen $&und $'verhalten sich wie die beiden Operanden in einem numerischen Kontext. Die Operanden werden verglichen <=>und das Ergebnis mit dem ersten Zeichen des Operators abgeglichen. Dann wird speziell auf Gleichheit und Ungleichheit eingegangen.

grc
quelle
4

CJam, 60 Bytes

Dieser Code scheint ein bisschen hässlich und möglicherweise nicht vollständig optimiert zu sein, aber er ist der beste, den ich bisher habe.

Probieren Sie es online aus.

q_A,sSer_S%@@-(])1\@z{~:X\:^i['=")<"P"(>"P'<'^'>PPP]=~e&X}/;

Erläuterung

q               "Read the input";
_A,sSer         "Copy the input and replace each digit with a space";
_S%             "Split around spaces to obtain the operation list";
@@-             "Remove operations from the input to obtain the operand list";
(])1\@z         "Remove the first operand from the list to be the initial left
                 operand, initialize the result to 1 (true), and pair up the
                 operations and remaining operands";
{               "For each operation-operand pair:";
  ~:X             "Let the operand be the right operand of this operation";
  \:^i            "Hash the operation (bitwise XOR of all characters)";
  [               "Begin cases:";
    '=              " 0: Equals";
    ")<"            " 1: Less than or equal to";
    P               " 2: (Invalid)";
    "(>"            " 3: Greater than or equal to";
    P               " 4: (Invalid)";
    '<              " 5: Less than";
    '^              " 6: Bitwise XOR (stand-in for not equal to)";
    '>              " 7: Greater than";
    P               " 8: (Invalid)";
    P               " 9: (Invalid)";
    P               "10: (Invalid)";
  ]=~             "Execute the case selected by the operation hash modulo 11";
  e&              "Compute the logical AND of the result and the value produced
                   by this operation to be the new result";
  X               "Let the right operand be the new left operand";
}/              "End for each";
;               "Clean up and implicitly print result";
Runer112
quelle
4

JavaScript (ES6) 110 116

Einfach: Scan-Zeichenfolge, c ist die aktuelle Ziffer, l ist die letzte Ziffer, o ist der Operator.

F=x=>(l='',[for(c of x)10-c?(v=!l||v&&(o<'<'?l!=c:(o[1]&&c==l)||(o<'='?l<c:o<'>'?c==l:l>c)),l=c,o=''):o+=c],v)

Test In der Firefox / FireBug-Konsole

;['3<=4!=9>3==3','3<=4!=4','5>5','8==8<9>0!=2>=1']
.forEach(s=>console.log(s,F(s)))

3 <= 4! = 9> 3 == 3 wahr
3 <= 4! = 4 falsch
5> 5 falsch
8 == 8 <9> 0! = 2> = 1 wahr

edc65
quelle
3

Haskell, 156 Bytes

r a=read[a]::Int
l"!"=(/=)
l"="=(==)
l">"=(>=)
l"<"=(<=)
k">"=(>)
k"<"=(<)
[]#_=1<2
(a:'=':b:c)#i=l[a]i(r b)&&c#r b
(a:b:c)#i=k[a]i(r b)&&c#r b
f(h:t)=t#r h

Anwendungsbeispiel:

f "3<=4!=9>3==3"        -> True
f "3<=4!=4"             -> False
f "5>5"                 -> False
f "8==8<9>0!=2>=1"      -> True

Ungolfed-Version:

digitToInt d = read [d] :: Int

lookup2 "!" = (/=)
lookup2 "=" = (==)
lookup2 ">" = (>=)
lookup2 "<" = (<=)

lookup1 ">" = (>)
lookup1 "<" = (<)

eval []              _ = True
eval (op:'=':d:rest) i = lookup2 [op] i (digitToInt d) && eval rest (digitToInt d)
eval (op:d:rest)     i = lookup1 [op] i (digitToInt d) && eval rest (digitToInt d)

evalChain (hd:rest) = eval rest (digitToInt hd)

evalEs werden zwei Argumente verwendet: Der zu analysierende String (der immer mit einem Vergleichsoperator beginnt) und eine Zahl, idie das linke Argument für den Vergleich ist (und in der vorherigen Runde das rechte Argument war). Der Operator wird zurückgegeben, lookup2wenn es sich um einen zweistelligen Operator handelt (überprüfen Sie nur das erste Zeichen, da das zweite immer ist =) und lookup1wenn es sich nur um ein einzelnes Zeichen handelt. evalruft sich rekursiv auf und kombiniert alle Rückgabewerte mit logischem und &&.

nimi
quelle
3

Gemeines Lisp - 300 185 169 165

(lambda(s)(loop for(a o b)on(mapcar'read-from-string(cdr(ppcre:split"([0-9]+)"s :with-registers-p t)))by #'cddr always(if o(funcall(case o(=='=)(!='/=)(t o))a b)t)))

Beispiel

(mapcar (lambda(s) ...)
       '("2<=3<=6>2<10!=3"
         "3<=4!=9>3==3" 
         "3<=4!=4" 
         "5>5"
         "8==8<9>0!=2>=1"))
=> (T T NIL NIL T)

Erläuterung

(lambda (s)
  (loop for (a o b) on (mapcar
                        'read-from-string
                        (cdr
                         (cl-ppcre:split "([0-9]+)" s
                                         :with-registers-p t))) by #'cddr
        always (if o
                   (funcall (case o
                                  (== '=)
                                  (!= '/=)
                                  (t o))
                            a b)
                   t)))
  • ppcre:splitSplits auf Ziffern; beispielsweise:

    (ppcre:split "([0-9]+)" "2<=3<=6>2<10!=3" :with-registers-p t)
    => ("" "2" "<=" "3" "<=" "6" ">" "2" "<" "10" "!=" "3")
    

    Beachten Sie die erste leere Zeichenfolge, die mit verworfen wird cdr

  • Die Zuordnung read-from-stringzu dieser Liste ruft die readFunktion für jede Zeichenfolge auf, die Symbole und Zahlen zurückgibt.

  • loop for (a op b) on '(3 < 5 > 2) by #'cddrdie Liste iteriert durch einen Schritt 2 , und somit gebunden a, opund bwie folgt für jeden aufeinanderfolgenden Durchlauf.

    a  op  b
    ----------
    3  <    5
    5  >    2
    2  nil  nil
    
  • alwaysprüft, ob der nächste Ausdruck immer wahr ist: entweder der Operator ist nil(so) oder das Ergebnis des Vergleichs gilt (so).

  • das casewählt eine Common-Lisp-Vergleichsfunktion gemäß dem zuvor gelesenen Symbol aus; da einige Operatoren in Lisp und der angegebenen Sprache identisch sind, können wir oim Standardfall einfach zurückgeben .

Core-Dump
quelle
1

Python 2, 95 102

t=1
n=o=3
for c in map(ord,raw_input()):
 o+=c
 if 47<c<58:t&=627>>(o-c+3*cmp(n,c))%13;n=c;o=0
print t

Die Schleife ist ein direkter Durchlauf der Zeichenfolge nacheinander. Der t&=...Teil ist, wo die Magie passiert. Grundsätzlich habe ich den Operator zusammen mit dem Wert cmp(lhs,rhs)(-1, 0 oder 1, je nachdem, ob lhskleiner, gleich oder größer als rhs). Das Ergebnis ist ein Schlüssel in einer Nachschlagetabelle, die 0 oder 1 ergibt, je nachdem, ob die Zahlen bei diesem Operator richtig verglichen werden. Welche Nachschlagetabelle fragst du? Es ist die Zahl 627 = 0001001110011binär. Den Rest erledigen bitweise Operatoren.

Dies funktioniert für die vier angegebenen Testfälle. Lassen Sie mich wissen, wenn Sie einen Fehler für einen anderen Fall finden. Ich habe es nicht sehr streng getestet.

DLosc
quelle
Sie müssen aals Eingabe übernehmen.
xnor
@xnor Hoppla. Korrigiert
DLosc
1

Javascript 101 Bytes

Ein anderer Ansatz als die hier veröffentlichte js-Lösung

F=(s,i=0,l=o="")=>[...s].every(c=>c>=0?[l^c,l==c,,l<c,l>c,l<=c,,l>=c]["!==<><=>=".search(o,l=c,o="")]:o+=c,l=o="")

console.log(F("3<=4!=9>3==3")==true)
console.log(F("3<=4!=4")==false)
console.log(F("5>5")==false)
console.log(F("8==8<9>0!=2>=1")==true)

DanielIndie
quelle
0

Java 8, 283 Bytes

s->{String[]a=s.split("\\d"),b=s.split("\\D+");int i=0,r=1,x,y;for(;i<a.length-1;)if((x=new Byte(b[i]))!=(y=new Byte(b[++i]))&(a[i].equals("=="))|(a[i].equals("!=")&x==y)|(a[i].equals(">")&x<=y)|(a[i].equals(">=")&x<y)|(a[i].equals("<")&x>=y)|(a[i].equals("<=")&x>y))r--;return r>0;}

Erläuterung:

Probieren Sie es hier aus.

s->{                            // Method with String parameter and boolean return-type
  String[]a=s.split("\\d"),     //  All the inequalities
          b=s.split("\\D+");    //  All the digits
  int i=0,                      //  Index-integer (starting at 0)
      r=1,                      //  Flag integer for the result, starting at 1
      x,y;                      //  Temp integer `x` and `y`
  for(;i<a.length-1;)           //  Loop from 0 to the length - 1
  if((x=new Byte(b[i]))!=(y=new Byte(b[++i]))&(a[i].equals("=="))
                                //   If "==" and `x` and `y` as int are not equal:
     |(a[i].equals("!=")&x==y)  //   Or "!=" and `x` and `y` are equal
     |(a[i].equals(">")&x<=y)   //   Or ">" and `x` is smaller or equal to `y`
     |(a[i].equals(">=")&x<y)   //   Or ">=" and `x` is smaller than `y`
     |(a[i].equals("<")&x>=y)   //   Or "<" and `x` is larger or equal to `y`
     |(a[i].equals("<=")&x>y))  //   Or "<=" and `x` is larger than `y`
    r--;                        //    Decrease `r` by 1
                                //  End of loop (implicit / single-line body)
  return r>0;                   //  Return if `r` is still 1
}                               // End of method
Kevin Cruijssen
quelle