Уравнения спичек


16

Ваша задача в этой задаче - проанализировать данное «уравнение спички», как это ...

введите описание изображения здесь

... и выяснить, можно ли превратить его в правильное уравнение путем перестановки совпадений. Если это так, вы должны вывести наименьшее количество ходов и полученное уравнение.

вход

Входные данные представляют собой строку, которую можно прочитать из STDIN, принять в качестве аргумента функции или даже сохранить в файле. Это уравнение, которое представляет расположение спичек и может быть описано с использованием следующего 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 ;

Примером правильного ввода будет 3+6-201=0+0+8.

задача

Рассмотрим следующую иллюстрацию, где каждой спичке присвоен номер:

положения спички

Теперь мы сопоставим каждый входной символ с соответствующими позициями спички следующим образом:

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

Каждую формулу ввода можно превратить в спичечное устройство. Например, уравнение «45 + 6 = 92» становится

введите описание изображения здесь

где неиспользованные спички закрашены серым. Ваша задача - найти наименьшее количество спичек, которые нужно переставить, чтобы уравнение было верным.

Выход

Мы различаем три возможных случая:

  • Если ввод недействителен (т.е. он не удовлетворяет вышеуказанному EBNF), выведите все, что вы хотите.
  • В противном случае, если есть способы превратить уравнение в правильное путем перестановки спичек, вы должны вывести как минимальное количество перестановок, так и соответствующее уравнение. Как и входные данные, выведенное уравнение также должно удовлетворять заданному EBNF. В приведенном выше примере правильный вывод будет 1и 46+6=52. Если для получающегося уравнения есть несколько возможностей, выведите любую из них.
  • В противном случае (поэтому, если входные данные верны, но нет способа сделать уравнение истинным), вы должны вывести -1.

Детали

  • Вам не разрешено удалять или добавлять совпадения. Это означает, что если вход построен из nспичек, выход также должен состоять из точноn спичек.
  • «Пустые» блоки спичек допускаются только в конце и в начале уравнения, а не в середине. Так, например, переход 7-1=6в 7 =6-1простое удаление -1с левой стороны и добавление его с правой стороны всего с 3 перестановками спичек не допускается.
  • Поскольку я действительно не рассматриваю сопоставление чисел с позициями спичек как интересную часть этой задачи, для плюс 20 байтов вы можете либо

    • получить доступ к файлу, в котором отображается (number/operation ↦ matchstick positions) хранится любым разумным способом, или
    • если ваш язык программирования поддерживает Mapтип данных, предположим, что у вас есть доступ к карте, которая предварительно (number/operation ↦ matchstick positions)инициализируется с помощью -mapping. Например, эта карта может выглядеть так:{(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})}

Примеры

Вход: 1+1=3Выход: 1 и1+1=2

Вход: 15+6=21Выход: 0 и15+6=21

Вход: 1=7Выход: -1

Вход: 950-250=750Выход: 2 и990-240=750

Вход: 1-2=9Выход: 1 и1+2=3

Вход: 20 + 3=04Выход: все

победитель

Это , поэтому выигрывает самый короткий правильный ответ (в байтах). Победитель будет выбран через неделю после публикации первого правильного ответа.


1
Пожалуйста, добавьте 0: 1, 2, 3, 4, 5, 6для согласованности
Не то, что Чарльз

О, спасибо, совсем как-то забыл об этом!
Во

@vauge Эй, должен ли '2 = 1-1' -> '2-1 = 1' вернуть 3 или 14 ходов, поскольку технически 2 нужно сдвинуть влево?
Cieric

@Cieric должно возвращать 3, просто потому, что вы можете поменять положение =(2 спички) и -(1 спичка) и оставить все числа там, где они есть. Однако, если 2 нужно было сдвинуть влево, вам также нужно будет подсчитать необходимые ходы.
Vauge

Есть ли ограничения на количество операций? Может ли вход быть похожим 1+1+2=3-6+10? И тот же вопрос о выходе.
Qwertiy

Ответы:


6

Javascript, 1069 байт

Я проверил его с помощью нескольких тестовых уравнений, и теперь, похоже, он работает все время ...

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}

Ну, это мой первый раз, когда я представляю ответ, поэтому я не вижу себя победителем. Это в основном метод грубой силы, чтобы выяснить все ответы, а затем он берет и возвращает самые маленькие из них в массиве. с первым аргументом, являющимся длиной, и вторым, являющимся массивом с выходными данными.

если вход «1-2 = 9», выход будет [1, [«1 + 2 = 3», «7-2 = 5»]]

и вот несжатый код:

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

Предупреждение: не делайте уравнений, таких как 950-250 = 750, он использует ~ 45 Matchsticks и потому что этот код использует грубую силу, это приведет к зависанию javascript.


Я полагаю, что вы можете объявить переменные, которые вы используете, такие как var kв циклах, как неиспользуемые параметры для функции, сохраняя 3 байта для каждого объявления.
rorlork

Я думаю, что пойду изучать еще несколько языков программирования и найду способ, не настолько грубый, чтобы попытаться действительно сбить этот байтовый отсчет.
Cieric

Я думаю, что ваше решение не является правильным, так как при расчете расстояния вы всегда выравниваете равные символы. В некоторых случаях это не оптимальный способ. Например, «2 = 1-1» можно преобразовать за 3 хода в «2-1 = 1», а выравнивание знаков «=» дает 14 ходов. Также я не вижу, как вы избегаете ведущих нулей. Например, 08=8для 80=8неверно.
Nutki

@nutki Да, я думаю, что могу это изменить. Я думал, что это было бы неправильно, хотя из-за того, что вам технически пришлось переместиться через 2, чтобы освободить место для -1
Cieric

@ nutki хорошо, да. Извините, я понимаю, что вы имеете в виду сейчас. Ну, я собираюсь исправить регулярное выражение и посмотреть, смогу ли я изменить код для расстояния редактирования.
Cieric

1

Perl, 334

Довольно быстро, пока решение достижимо за 1 или 2 хода. Когда нет решения, вы ждете долгого ожидания, даже в малейшем случае 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}

Пример:

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

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

Это не приведет к поиску решений, которые изменят длину равенства, как 11=4-> 2 11=11, но я не уверен, что это будет разрешено.


1
Решения, которые изменяют длину уравнения, допускаются, если они следуют EBNF, упомянутому в вопросе. Следовательно, они также должны быть найдены вашей функцией.
Vauge

@ Vauge, да, я вижу, что это может быть выведено из раздела «пустые блоки мастики» в деталях. Я не буду добавлять его к этому решению, хотя, хотя оно может работать, оно сделает его еще медленнее.
Nutki

@vauge Не хочу показаться грубым, но если код не исправлен, он все равно будет учитываться?
Cieric

@Cieric Если нет другого решения, которое бы обрабатывало все эти случаи, тогда да, оно будет засчитано. Однако, если к концу этого задания будут какие-либо полностью рабочие ответы, я приму самый короткий из них.
Vauge

@ vauge хорошо, просто проверяю, мне нужно только убедиться, что число ходов верное, пока оно всегда отображает правильное выходное уравнение.
Cieric
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.