Evaluar una cadena de desigualdades.

17

Escriba código para evaluar si una cadena de desigualdades es verdadera o falsa. Un ejemplo de entrada es la cadena

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

Esto es cierto porque cada uno de sus componentes es verdadero:

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

Entrada:

Una cadena que representa una cadena de una o más desigualdades. Los operadores de comparación permitidos son

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

Los números permitidos son números de un solo dígito 0hasta 9. No habrá espacios, paréntesis u otros símbolos.

Salida:

La corrección de la desigualdad como un valor consistente de Verdad o Falsey . Consistente significa que cada salida de Truthy es igual y cada salida de Falsey es igual.

Restricción:

La intención de este desafío es que usted escriba código que procese las desigualdades, en lugar de hacer que las evalúen como código, incluso para una única desigualdad en la cadena. Como tal, los métodos como Python evaly execque evalúan o ejecutan código están prohibidos. También lo son las funciones que buscan un método u operador dado su nombre como una cadena. Tampoco está permitido iniciar procesos o programas para hacer la evaluación por usted.

Casos de prueba:

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

3<=4!=4
False

5>5
False

8==8<9>0!=2>=1
True
xnor
fuente
¿Podemos aceptar entradas con signos de desigualdad Unicode como ≤ y ≥ en lugar de <= y> =?
FUZxxl
@FUZxxl No puedes.
xnor

Respuestas:

7

Rubí, 71 + 1 = 72

Con el indicador de línea de comando -n, ejecute

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

Genera todas las posibles expresiones regulares que fallan y comprueba si la cadena de entrada coincide con alguna de ellas. Salidas truesi ninguna lo hace, de lo contrariofalse . Toma datos a través de STDIN, separados por nuevas líneas.

Trucos:

  • Obtenemos todos los pares de dígitos posibles haciendo un bucle de 0 a 99 y extrayendo los dígitos 10 y 1.
  • La única comparación real que hacemos es a<=>b, que devuelve -1,0, o 1 por menos de, igual o mayor. Todos estos se dividen en diferentes elementos de una matriz de tres cadenas, encontrando la expresión regular para las comparaciones que no coinciden.
histocrat
fuente
¡Qué estrategia tan inteligente!
xnor
6

Perl, 82

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

Imprime 1 cuando es verdadero y una línea en blanco cuando es falso, ya que la cadena vacía es el principal valor de falsey de Perl.

El bucle while pasa sobre la cadena que coincide con la expresión regular \d(.)(=?). Luego las variables $1y $2corresponden a los caracteres del operador, y las variables especiales $&y $'se comportarán como los dos operandos en un contexto numérico. Los operandos se comparan con<=> y el resultado el primer carácter del operador. Entonces la igualdad y la desigualdad se tratan especialmente.

grc
fuente
4

CJam, 60 bytes

Este código parece un poco feo y potencialmente no está completamente optimizado, pero es el mejor que tengo hasta ahora.

Pruébalo en línea.

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

Explicación

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
fuente
4

JavaScript (ES6) 110 116

Directo: cadena de escaneo, c es el dígito actual, l es el último dígito, o es el operador.

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)

Prueba en la consola 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 verdadero
3 <= 4! = 4 falso
5> 5 falso
8 == 8 <9> 0! = 2> = 1 verdadero

edc65
fuente
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

Ejemplo de uso:

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

Versión sin golf:

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)

evaltoma dos argumentos: la cadena para analizar (comenzando siempre con un operador de comparación) y un número ique es el argumento izquierdo para la comparación (y fue el argumento correcto en la ronda anterior). El operador se devuelve lookup2si es un operador de dos caracteres (marque solo el primer carácter, porque el segundo siempre es =) y lookup1si es solo un carácter. evalse llama recursivamente y combina todos los valores de retorno con lógico y &&.

nimi
fuente
3

Lisp común 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)))

Ejemplo

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

Explicación

(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 divide en dígitos; por ejemplo:

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

    Observe la primera cadena vacía, que se descarta usando cdr

  • La asignación read-from-stringa esta lista llama a la readfunción para cada cadena, que devuelve símbolos y números.

  • loop for (a op b) on '(3 < 5 > 2) by #'cddritera sobre la lista en un paso de 2 y, por lo tanto a, se une , opy de la bsiguiente manera, para cada pase sucesivo.

    a  op  b
    ----------
    3  <    5
    5  >    2
    2  nil  nil
    
  • alwayscomprueba si la siguiente expresión es siempre verdadera: el operador es nil(ver arriba) o el resultado de las retenciones de comparación (ver abajo).

  • los caseselecciona una función de comparación Common-Lisp, de acuerdo con el símbolo leído anteriormente; Dado que algunos operadores son idénticos en Lisp y en el idioma dado, simplemente podemos regresar oen el caso predeterminado.

volcado de memoria
fuente
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

El bucle es un paso directo a través de la cadena de un carácter a la vez. La t&=...parte es donde sucede la magia. Básicamente, hash el operador junto con el valor de cmp(lhs,rhs)(-1, 0 o 1 dependiendo de si lhses menor, igual o mayor que rhs). El resultado es una clave en una tabla de búsqueda que da 0 o 1 dependiendo de si los números se comparan correctamente dado ese operador. ¿Qué tabla de búsqueda, preguntas? Es el número 627 = 0001001110011en binario. Los operadores bit a bit hacen el resto.

Esto funciona en los cuatro casos de prueba dados; avíseme si encuentra un error para otro caso. No lo he probado muy rigurosamente.

DLosc
fuente
Necesita tomar acomo entrada.
xnor
@xnor Whoops. Corregido
DLosc
1

Javascript 101 bytes

un enfoque diferente de la solución js publicada aquí

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

Explicación:

Pruébalo aquí

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
fuente