Equações de palito de fósforo


16

Sua tarefa neste desafio é analisar uma determinada "Equação de palito de fósforo" como esta ...

insira a descrição da imagem aqui

... e descobrir se ela pode ser transformada em uma equação válida, reorganizando as correspondências. Nesse caso, você deve emitir o menor número de movimentos para fazê-lo e a equação resultante.

Entrada

A entrada é uma String que pode ser lida em STDIN, usada como argumento de função ou mesmo armazenada em um arquivo. É uma equação que representa um arranjo de palito de fósforo e pode ser descrita usando o seguinte 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 ;

Um exemplo para uma entrada válida seria 3+6-201=0+0+8.

Tarefa

Considere a ilustração a seguir, onde cada palito de fósforo tem um número atribuído:

posições do palito de fósforo

Agora, mapeamos cada símbolo de entrada para as posições correspondentes do palito de fósforo da seguinte maneira:

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 pode ser transformada em um arranjo de palito de fósforo. Por exemplo, a equação "45 + 6 = 92" se torna

insira a descrição da imagem aqui

onde palitos de fósforo não utilizados estão acinzentados. Sua tarefa é descobrir o menor número de palitos de fósforo que precisam ser reorganizados para tornar a equação válida.

Resultado

Distinguimos entre três casos possíveis:

  • Se a entrada não for válida (ou seja, não atender ao EBNF acima), faça o que você quiser.
  • Caso contrário, se há maneiras de transformar a equação para um válido, reorganizando os palitos de fósforo, você tem que saída tanto o número mínimo de rearranjos e da equação correspondente. Assim como a entrada, a equação emitida também deve satisfazer o EBNF fornecido. No exemplo acima, a saída correta seria 1e 46+6=52. Se houver várias possibilidades para a equação resultante, produza uma delas.
  • Caso contrário (se a entrada for válida, mas não houver maneira de tornar a equação verdadeira), é necessário gerar a saída -1.

Detalhes

  • Você não tem permissão para remover ou adicionar correspondências. Isso significa que, se a entrada for construída com npalitos de fósforo, a saída também deverá consistir em exatamente npalitos de fósforo.
  • Blocos de fósforo "vazios" são permitidos apenas no final e no início de uma equação, não no meio. Por exemplo, transformar 7-1=6- se em 7 =6-1simplesmente remover -1do lado esquerdo e adicioná-lo no lado direito com apenas 3 rearranjos de palitos de fósforo não é permitido.
  • Como eu realmente não vejo o mapeamento de números para posições de palitos de fósforo como uma parte interessante desse desafio, para mais de 20 bytes , você pode

    • acessar um arquivo no qual o mapeamento (number/operation ↦ matchstick positions)é armazenado de forma razoável ou
    • se sua linguagem de programação suportar um Maptipo de dados, suponha que você tenha acesso a um mapa pré-inicializado com o (number/operation ↦ matchstick positions)mapeamento. Este mapa pode, por exemplo, ter a seguinte aparência:{(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})}

Exemplos

Entrada: 1+1=3Saída: 1 e1+1=2

Entrada: 15+6=21Saída: 0 e15+6=21

Entrada: 1=7Saída: -1

Entrada: 950-250=750Saída: 2 e990-240=750

Entrada: 1-2=9Saída: 1 e1+2=3

Entrada: 20 + 3=04saída: nada

Vencedora

Isso é , então a resposta correta mais curta (em bytes) vence. O vencedor será escolhido uma semana após a publicação da primeira resposta correta.


11
Por favor, adicione 0: 1, 2, 3, 4, 5, 6a consistência
Não que Charles

Oh obrigado, esqueci totalmente disso de alguma forma!
vauge

@vauge Hey deve '2 = 1-1' -> '2-1 = 1' retornar 3 ou 14 movimentos, já que os 2 tecnicamente precisam ser movidos para a esquerda?
Cieric

@Cieric deve retornar 3, simplesmente porque você pode mudar a posição de =(2 palitos de fósforo) e -(1 palito de fósforo) e deixar todos os números onde estão. Se, no entanto, os dois tivessem que ser movidos para a esquerda, você também precisaria contar os movimentos necessários.
vauge

Existe uma limitação no número de operações? A entrada pode ser assim 1+1+2=3-6+10? E mesma pergunta sobre a saída.
Qwertiy

Respostas:


6

Javascript, 1069 bytes

Eu testei com algumas equações de teste e parece funcionar o tempo todo agora ...

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}

Bem, esta é a minha primeira vez em enviar uma resposta, então não me vejo ganhando. Este é basicamente um método de força bruta para descobrir todas as respostas e, em seguida, ele pega e retorna as menores em uma matriz. com o primeiro argumento sendo o comprimento e o segundo sendo uma matriz com as saídas.

se a entrada for "1-2 = 9", a saída será [1, ["1 + 2 = 3", "7-2 = 5"]]

e aqui está o código descompactado:

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

Aviso: Não faça equações como 950-250 = 750, ele usa ~ 45 palitos de fósforo e, como esse código usa força bruta, fará com que o javascript seja interrompido.


Eu acredito que você pode declarar as variáveis ​​que você usa, como var knos loops, como parâmetros não utilizados para a função, economizando 3 bytes para cada declaração.
rorlork

Eu acho que vou aprender mais algumas linguagens de programação e descobrir uma maneira não tão bruta de tentar e realmente derrubar a contagem de bytes.
Cieric

Acho que sua solução não está correta, pois quando você calcula a distância, sempre alinha os caracteres iguais. Em alguns casos, não é o caminho ideal. Por exemplo, '2 = 1-1' pode ser transformado em 3 movimentos em '2-1 = 1', enquanto o alinhamento dos sinais '=' fornece 14 movimentos. Também não vejo como evitar zeros à esquerda. Por exemplo, 08=8para 80=8está incorreto.
nutki

@ nutki Sim, acho que posso mudar isso. Eu estava pensando que isso seria errado, devido a você tecnicamente ter que passar sobre o 2 para dar espaço para o -1
Cieric 2/15

@ nutki ok, sim. Desculpe, entendi o que você quer dizer agora. Bem, vou corrigir o regex e ver se consigo alterar o código para a distância de edição.
Cieric

1

Perl, 334

Bastante rápido, desde que a solução seja alcançável em 1 ou 2 movimentos. Quando não há solução, você aguarda uma longa espera, mesmo no menor caso 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}

Exemplo:

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

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

Isso não encontrará soluções que alterem o comprimento da equasão como 11=4-> 2 11=11, mas não tenho certeza se isso seria permitido.


11
Soluções que alteram o comprimento da equação são permitidas desde que sigam o EBNF mencionado na pergunta. Portanto, eles também devem ser encontrados por sua função.
usar o seguinte comando

@vauge, sim, posso ver que isso pode ser deduzido da seção "blocos vazios de máquinas" nos detalhes. Não o adicionarei a esta solução, embora, enquanto pudesse funcionar, tornaria ainda mais lenta.
nutki

@vauge Eu não quero parecer grosseiro, mas se o código não for corrigido, ele ainda conta?
Cieric

@ Cieric Se não houver outra solução que lide com todos esses casos, sim, isso contará. No entanto, se houver respostas completas até o final deste desafio, aceitarei as mais curtas.
vauge

@ okuge ok apenas verificando Eu só tenho que garantir que o número de movimentos esteja correto até o momento, sempre exibe a equação de saída correta.
Cieric
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.