Ecuaciones de fósforos

16

Su tarea en este desafío es analizar una determinada "Ecuación de Matchstick" como esta ...

ingrese la descripción de la imagen aquí

... y para averiguar si se puede convertir en una ecuación válida reorganizando las coincidencias. Si es así, debe generar el menor número de movimientos para hacerlo y la ecuación resultante.

Entrada

La entrada es una cadena que puede leerse desde STDIN, tomarse como un argumento de función o incluso almacenarse en un archivo. Es una ecuación que representa una disposición de fósforo y se puede describir usando el siguiente EBNF:

input = term, "=", term ;
term = number | (term, ("+" | "-"), term) ;
number = "0" | (numeralExceptZero , {numeral}) ;
numeralExceptZero = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
numeral = "0" | numeralExceptZero ;

Un ejemplo para una entrada válida sería 3+6-201=0+0+8.

Tarea

Considere la siguiente ilustración donde cada cerilla tiene un número asignado:

posiciones de cerillas

Ahora asignamos cada símbolo de entrada a las posiciones de los fósforos correspondientes de la siguiente manera:

0 ↦ 1,2,3,4,5,6
1 ↦ 4,5
2 ↦ 2,3,5,6,8
3 ↦ 3,4,5,6,8
4 ↦ 1,4,5,8
5 ↦ 1,3,4,6,8
6 ↦ 1,2,3,4,6,8
7 ↦ 4,5,6
8 ↦ 1,2,3,4,5,6,8
9 ↦ 1,3,4,5,6,8
- ↦ 8
+ ↦ 8,10
= ↦ 7,9

Cada fórmula de entrada se puede convertir en una disposición de fósforo. Por ejemplo, la ecuación "45 + 6 = 92" se convierte en

ingrese la descripción de la imagen aquí

donde los fósforos no utilizados están en gris. Su tarea es encontrar el menor número de fósforos que deben reorganizarse para que la ecuación sea válida.

Salida

Distinguimos entre tres posibles casos:

  • Si la entrada no es válida (es decir, no satisface el EBNF anterior), envíe lo que desee.
  • De lo contrario, si hay formas de convertir la ecuación en una válida reorganizando las coincidencias, debe generar tanto el número mínimo de reordenamientos como la ecuación correspondiente. Al igual que la entrada, la ecuación de salida también debe satisfacer el EBNF dado. En el ejemplo anterior, la salida correcta sería 1y 46+6=52. Si existen múltiples posibilidades para la ecuación resultante, envíe cualquiera de ellas.
  • De lo contrario (si la entrada es válida pero no hay forma de hacer que la ecuación sea verdadera), tiene que dar salida -1.

Detalles

  • No está permitido eliminar ni agregar coincidencias. Eso significa que, si la entrada está construida con nfósforos, la salida también debe consistir exactamente en nfósforos.
  • Los bloques de fósforos "vacíos" solo se permiten al final y al comienzo de una ecuación, no en el medio. Así, por ejemplo, convirtiendo 7-1=6en 7 =6-1por la simple eliminación -1no está permitido desde el lado izquierdo y añadiéndolo en el lado derecho con sólo 3 reordenamientos cerillas.
  • Como realmente no veo el mapeo de números a posiciones de palillos como una parte interesante de este desafío, por un plus de 20 bytes , puede

    • acceder a un archivo en el que la asignación (number/operation ↦ matchstick positions)se almacena de manera razonable, o
    • si su lenguaje de programación admite un Maptipo de datos, suponga que tiene acceso a un mapa preinicializado con el mapa (number/operation ↦ matchstick positions). Este mapa puede, por ejemplo, verse así:{(0,{1,2,3,4,5,6}),(1,{4,5}),(2,{2,3,5,6,8}),(3,{3,4,5,6,8}), ..., (-,{8}),(+,{8,10}),(=,{7,9})}

Ejemplos

Entrada: 1+1=3Salida: 1 y1+1=2

Entrada: 15+6=21Salida: 0 y15+6=21

Entrada: 1=7Salida: -1

Entrada: 950-250=750Salida: 2 y990-240=750

Entrada: 1-2=9Salida: 1 y1+2=3

Entrada: 20 + 3=04Salida: cualquier cosa

Ganador

Este es el , por lo que gana la respuesta correcta más corta (en bytes). El ganador será elegido una semana después de que se publique la primera respuesta correcta.

vagabundo
fuente
1
Agregue 0: 1, 2, 3, 4, 5, 6por coherencia
no es que Charles
¡Oh, gracias, se olvidó por completo de eso de alguna manera!
Vauge
@vauge Hey, ¿debería '2 = 1-1' -> '2-1 = 1' devolver 3 o 14 movimientos ya que técnicamente los 2 deben moverse a la izquierda?
Cieric
@Cieric debería devolver 3, simplemente porque puede cambiar la posición de =(2 fósforos) y -(1 fósforo) y dejar todos los números donde están. Sin embargo, si el 2 tuviera que moverse hacia la izquierda, también tendría que contar los movimientos requeridos.
Vauge
¿Hay alguna limitación en el número de operaciones? ¿Puede ser como la entrada 1+1+2=3-6+10? Y la misma pregunta sobre la salida.
Qwertiy

Respuestas:

6

Javascript, 1069 bytes

Lo he probado con bastantes ecuaciones de prueba y parece que funciona todo el tiempo ahora ...

function w(t){function B(c,f){d=(c.length>f.length?f:c).split("");e=(c.length>f.length?c:f).split("");longer=Math.max(d.length,e.length);if(0!==d.length&&0!==e.length){c=[];for(x in d)for(y in c[x]=[],e)c[x][y]=1<y-x?-1:function(c,n){r=0;for(j in n)-1<c.indexOf(n[j])&&r++;return c.length+n.length-2*r}(a[d[x]],a[e[y]]);return v=function(f,n){for(var h=f.length-2;0<=h;h--)c[n.length-1][h]+=c[n.length-1][h+1];for(h=f.length-2;0<=h;h--)for(var q=0;q<n.length-1;q++)1>=h-q&&(c[q][h]+=-1==c[q][h+1]?c[q+1][h+1]:Math.min(c[q+1][h+1],c[q][h+1]));return c[0][0]/2}(e,d)}return-1}a=[[1,2,3,4,5,6],[4,5],[2,3,5,6,8],[3,4,5,6,8],[1,4,5,8],[1,3,4,6,8],[1,2,3,4,6,8],[4,5,6],[1,2,3,4,5,6,8],[1,3,4,5,6,8]];a["+"]=[8,0];a["-"]=[8];a["="]=[7,9];a[" "]=[];l=0;p=[];u=[];r=/^([1-9]\d*|0)([+-]([1-9]\d*|0))*=([1-9]\d*|0)([+-]([1-9]\d*|0))*$/;b=/(=.*=|[+=-]{2,}|^[+=-])/;if(!t.match(r))return-1;g=function(c,f,t){if(0===t&&f.match(r)&&eval(f.replace("=","==")))c.push(f);else for(var n in a)t>=a[n].length&&" "!=n&&!(f+n).match(b)&&g(c,f+n,t-a[n].length)};g(p,"",function(c){m=0;for(var f in c)m+=a[c[f]].length;return m}(t.split("")));for(var z in p)k=B(t,p[z]),u[k]||(u[k]=[]),u[k].push(p[z]);for(var A in u)return[A,u[A]];return-1}

Bueno, esta es la primera vez que envío una respuesta, así que no me veo ganando. Este es básicamente un método de fuerza bruta para calcular todas las respuestas y luego toma y devuelve las más pequeñas en una matriz. siendo el primer argumento la longitud y el segundo una matriz con las salidas.

si la entrada es "1-2 = 9", la salida es [1, ["1 + 2 = 3", "7-2 = 5"]]

y aquí está el código sin comprimir:

function ms(s) {
a=[[1,2,3,4,5,6],[4,5],[2,3,5,6,8],[3,4,5,6,8],[1,4,5,8],[1,3,4,6,8],[1,2,3,4,6,8],[4,5,6],[1,2,3,4,5,6,8],[1,3,4,5,6,8]];
a["+"] = [8, 0];
a["-"] = [8];
a["="] = [7, 9];
a[" "] = [];
l = 0;
p = [];
u = [];
r = /^([1-9]\d*|0)([+-]([1-9]\d*|0))*=([1-9]\d*|0)([+-]([1-9]\d*|0))*$/;
b = /(=.*=|[+=-]{2,}|^[+=-])/;
if (!s.match(r)) return -1;
function f(g,h)
{
    d=(g.length>h.length?h:g).split('');
    e=(g.length>h.length?g:h).split('');
    longer=Math.max(d.length, e.length);
    if(0!==d.length&&0!==e.length)
    {
        g=[];
        for(x in d)
        {
            g[x]=[];
            for(y in e)
            {
                g[x][y]=(y-x>1)?-1:function(g, h){r=0;for(j in h)if(g.indexOf(h[j])>-1)r++;return g.length+h.length-2*r;}(a[d[x]],a[e[y]]);
            }
        }
        v=function(d,e)
        {
        for(var y=d.length-2;y>=0;y--) g[e.length-1][y]+=g[e.length-1][y+1];
        for(var y=d.length-2;y>=0;y--)
            for(var x=0;x<e.length-1;x++)
                if(y-x<=1)
                    g[x][y]+=g[x][y+1]==-1?g[x+1][y+1]:Math.min(g[x+1][y+1], g[x][y+1]);
        return g[0][0]/2}(e,d)
        return v
    }
    return -1;
}
g=function(n, s, i){if (i===0 && s.match(r) && eval(s.replace('=','=='))){n.push(s);return;}for (var c in a) if(i>=a[c].length && c!=" " && !(s+c).match(b)) g(n, s+c, i-a[c].length);};
g(p, "", function(q){m=0;for(var t in q)m+=a[q[t]].length;return m}(s.split('')));
for (var i in p)
{
    k=f(s, p[i]);
    if (!u[k]) u[k] = [];
    u[k].push(p[i]);
}
for (var q in u) return [q, u[q]];
return -1;
}

Advertencia: No haga ecuaciones como 950-250 = 750, usa ~ 45 Matchsticks y, dado que este código usa fuerza bruta, hará que se bloquee JavaScript.

Cierico
fuente
Creo que puede declarar las variables que usa, como var ken los bucles, como parámetros no utilizados para la función, ahorrando 3 bytes para cada declaración.
rorlork
Creo que voy a aprender algunos lenguajes de programación más y descubriré una forma de fuerza no tan bruta para tratar de eliminar esa cuenta regresiva de bytes.
Cieric
Creo que su solución no es correcta, ya que cuando calcula la distancia siempre alinea los caracteres iguales. En algunos casos no es la forma óptima. Por ejemplo, '2 = 1-1' se puede transformar en 3 movimientos en '2-1 = 1', mientras que alinear los signos '=' da 14 movimientos. Además, no veo cómo evitas los ceros a la izquierda. Por ejemplo 08=8para 80=8es incorrecto.
nutki
@nutki Sí, creo que puedo cambiar eso. Sin embargo, estaba pensando que estaría mal debido a que técnicamente tienes que moverte sobre los 2 para dejar espacio para el -1
Cieric
@nutki está bien, sí. Lo siento, veo lo que quieres decir ahora. Bueno, voy a arreglar la expresión regular y ver si puedo cambiar el código para la distancia de edición.
Cieric
1

Perl, 334

Bastante rápido siempre que la solución sea accesible en 1 o 2 movimientos. Cuando no hay solución, puede esperar mucho tiempo incluso en el caso más pequeño de 1=7.

#!perl -p
@y=map{sprintf"%010b",$_}63,24,118,124,89,109,111,56,127,125,64,192,768;
$y{$z{$y[$c++]}=$_}=$y[$c]for 0..9,qw(- + =);
$"="|";$l=s/./$y{$&}/g;$x{$_}=1;for$m(0..y/1//){
last if$_=(map"$m $_",grep{s/@y/$z{$&}/g==$l&&/^\d.*\d$/&!/\D\D/&!/\b0\d/&y/=//==1&&eval s/=/==/r}keys%x)[0];
$_=-1;s/0/"$`1$'"=~s!1!$x{"$`0$'"}=1!ger/eg for keys%x}

Ejemplo:

$ time perl ~/matchstick.pl <<<950-250=750
2 990-250=740

real    0m39.835s
user    0m39.414s
sys 0m0.380s

Esto no encontrará soluciones que cambien la longitud de la ecuación como 11=4-> 2 11=11, pero no estoy seguro de que esto esté permitido.

nutki
fuente
1
Las soluciones que cambian la longitud de la ecuación están permitidas siempre que sigan el EBNF mencionado en la pregunta. Por lo tanto, también deben ser encontrados por su función.
Vauge
@vauge, sí, puedo ver que podría inferirse de la sección "bloques de barras de máquinas vacías" en los detalles. Sin embargo, no lo agregaré a esta solución, ya que si bien podría funcionar, lo haría aún más lento.
nutki
@vauge No quiero parecer grosero, pero si el código no está arreglado, ¿seguirá contando?
Cieric
@Cieric Si no hay otra solución que maneje todos esos casos, entonces sí, contará. Sin embargo, si al final de este desafío hay respuestas totalmente operativas , aceptaré la más breve.
Vauge
@vauge está bien solo comprobando Solo tengo que asegurarme de que el número de movimientos sea correcto hasta ahora, siempre muestra la ecuación de salida correcta.
Cieric