Évaluer une chaîne d'inégalités

17

Écrivez du code pour évaluer si une chaîne d'inégalités est vraie ou fausse. Un exemple d'entrée est la chaîne

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

Cela est vrai car chacun de ses composants est vrai:

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

Contribution:

Une chaîne qui représente une chaîne d'une ou plusieurs inégalités. Les opérateurs de comparaison autorisés sont

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

Les numéros autorisés sont des numéros à un chiffre 0jusqu'à 9. Il n'y aura pas d'espaces, de parenthèses ou d'autres symboles.

Production:

La justesse de l'inégalité en tant que valeur cohérente de Truthy ou Falsey . Cohérent signifie que chaque sortie Truthy est la même et que chaque sortie Falsey est la même.

Restriction:

Le but de ce défi est que vous écriviez du code qui traite les inégalités, plutôt que de les évaluer en tant que code, même pour une seule inégalité dans la chaîne. En tant que tel, les méthodes comme Python evalet execqui évaluent ou exécutent du code sont interdites. Il en va de même pour les fonctions qui recherchent une méthode ou un opérateur en fonction de son nom sous forme de chaîne. Il n'est pas non plus permis de lancer des processus ou des programmes pour faire l'évaluation pour vous.

Cas de test:

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

3<=4!=4
False

5>5
False

8==8<9>0!=2>=1
True
xnor
la source
Pouvons-nous accepter une entrée avec des signes d'inégalité Unicode comme ≤ et ≥ au lieu de <= et> =?
FUZxxl
@FUZxxl Vous ne pouvez pas.
xnor

Réponses:

7

Rubis, 71 + 1 = 72

Avec l'indicateur de ligne de commande -n, exécutez

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

Génère toutes les expressions régulières pouvant échouer et vérifie si la chaîne d'entrée correspond à l'une d'entre elles. Sorties truesi aucun ne le fait, sinon false. Prend entrée via STDIN, séparé par des retours à la ligne.

Des trucs:

  • Nous obtenons toutes les paires de chiffres possibles en bouclant de 0 à 99 et en extrayant les chiffres 10s et 1s.
  • La seule comparaison réelle que nous faisons est a<=>b, qui renvoie -1,0, ou 1 pour inférieur à, égal ou supérieur. Tous ces éléments se répartissent en différents éléments d'un tableau à trois chaînes, trouvant l'expression régulière pour les comparaisons qui ne correspondent pas.
histocrate
la source
Quelle stratégie intelligente!
2015
6

Perl, 82

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

Imprime 1 lorsqu'elle est vraie et une ligne vierge lorsqu'elle est fausse, car la chaîne vide est la valeur de falsey principale de Perl.

La boucle while parcourt la chaîne correspondant à l'expression régulière \d(.)(=?). Ensuite, les variables $1et $2correspondent aux caractères de l'opérateur, et les variables spéciales $&et $'se comporteront comme les deux opérandes dans un contexte numérique. Les opérandes sont comparés <=>et le résultat est comparé au premier caractère de l'opérateur. Ensuite, l'égalité et l'inégalité sont traitées spécialement.

grc
la source
4

CJam, 60 octets

Ce code semble un peu moche et potentiellement pas entièrement optimisé, mais c'est le meilleur que j'ai eu jusqu'à présent.

Essayez-le en ligne.

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

Explication

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
la source
4

JavaScript (ES6) 110 116

Simple: chaîne de balayage, c est le chiffre actuel, l est le dernier chiffre, o est l'opérateur.

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 dans la console Firefox / FireBug

;['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 vrai
3 <= 4! = 4 faux
5> 5 faux
8 == 8 <9> 0! = 2> = 1 vrai

edc65
la source
3

Haskell, 156 octets

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

Exemple d'utilisation:

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

Version non golfée:

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)

evalprend deux arguments: la chaîne à analyser (en commençant toujours par un opérateur de comparaison) et un nombre iqui est l'argument de gauche pour la comparaison (et qui était l'argument de droite au tour précédent). L'opérateur est retourné par lookup2s'il s'agit d'un opérateur à deux caractères (ne cochez que le 1er caractère, car le 2e l'est toujours =) et par lookup1s'il ne s'agit que d'un seul caractère. evals'appelle de manière récursive et combine toutes les valeurs de retour avec logique et &&.

nimi
la source
3

Lisp commun - 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)))

Exemple

(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)

Explication

(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:splitse divise en chiffres; par exemple:

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

    Remarquez la première chaîne vide, qui est supprimée à l'aide de cdr

  • Le mappage read-from-stringà cette liste appelle la readfonction pour chaque chaîne, qui renvoie des symboles et des nombres.

  • loop for (a op b) on '(3 < 5 > 2) by #'cddritère la liste par une étape de 2 et lie ainsi a, opet bcomme suit, pour chaque passage successif.

    a  op  b
    ----------
    3  <    5
    5  >    2
    2  nil  nil
    
  • alwaysvérifie si l'expression suivante est toujours vraie: soit l'opérateur est nil(voir ci-dessus), soit le résultat de la comparaison est valide (voir ci-dessous).

  • le casesélectionne une fonction de comparaison Common-Lisp, selon le symbole lu précédemment; puisque certains opérateurs sont identiques en Lisp et dans le langage donné, nous pouvons simplement retourner odans le cas par défaut.

coredump
la source
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

La boucle est un passage simple à travers la chaîne un caractère à la fois. C'est t&=...là que la magie opère. Fondamentalement, je hache l'opérateur avec la valeur de cmp(lhs,rhs)(-1, 0 ou 1 selon que if lhsest inférieur, égal ou supérieur à rhs). Le résultat est une clé dans une table de recherche qui donne 0 ou 1 selon que les nombres se comparent correctement en fonction de cet opérateur. Quelle table de consultation, demandez-vous? C'est le nombre 627 = 0001001110011en binaire. Les opérateurs au niveau du bit font le reste.

Cela fonctionne sur les quatre cas de test donnés; faites-moi savoir si vous trouvez une erreur pour un autre cas. Je ne l'ai pas testé très rigoureusement.

DLosc
la source
Vous devez prendre en aentrée.
xnor
@xnor Whoops. Corrigée.
DLosc
1

Javascript 101 octets

une approche différente de la solution js publiée ici

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
la source
0

Java 8, 283 octets

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;}

Explication:

Essayez-le ici.

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
la source