Зрівняння рівнянь


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

@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

Перл, 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.