Обмен номерами [закрыт]

10

Это обычная головоломка, которую многие из вас решили вручную. Теперь пришло время написать алгоритм для решения того же.

Есть две одинаковые палочки, выстроенные в линию с двух разных сторон, обращенных друг к другу. Между ними есть одно пустое пространство. Скажите что-то вроде следующего рисунка (если общее количество совпадений равно 4).

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

Каждая палка может либо скользить на один шаг вперед (если непосредственное переднее пространство свободно), либо ее можно перепрыгнуть через одну палку спереди и приземлиться в свободное пространство (если это пространство свободно). Перемещение в обратном направлении невозможно (даже свободное место). Обратный прыжок также не допускается. Только один ход разрешен за один шаг.

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

Например: если есть всего 2 спички (по 1 с каждой стороны), то шаги будут:

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

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

На следующем рисунке описаны ходы с 4 спичками (по 2 с каждой стороны):

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

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

[Предположение: вход может быть любым четным числом от 02 до 14 (т.е. от 1 до 7 совпадающих палочек на каждой стороне). Для входных данных, выходящих за пределы этого диапазона, вам не нужно выполнять какую-либо проверку, а также не нужно предоставлять никаких сообщений об ошибках. Примечание. В выходных данных каждый шаг отделяется знаком «|». (труба) персонажа. Программисты на языке COBOL всегда должны принимать PIC 9 (2) в качестве размера ввода и могут также предполагать, что вывод имеет фиксированную максимальную длину 450 символов, дополненную пробелами справа.]


Пример ввода:

02  

Пример вывода:

01To02|03To01|02To03|


Пример ввода:

04  

Пример вывода:

02To03|04To02|05To04|03To05|01To03|02To01|04To02|03To04|


Пример ввода:

06  

Пример вывода:

03To04|05To03|06To05|04To06|02To04|01To02|03To01|05To03|07To05|06To07|04To06|02To04|03To02|05To03|04To05|
user2076421
источник
Если вы не можете включить изображения напрямую, можете ли вы предоставить ссылки для кого-то другого, чтобы редактировать их?
Питер Тейлор
2
Я сделал несколько быстрых изображений. Надеемся, что они соответствуют первоначальному замыслу автора.
Примо
3
Условие для победы?
Шмиддты

Ответы:

3

APL 129

Приведенный ниже код принимает экранный ввод и выводит на экран в указанном формате:

n←n,n++\1↓z←(⌽z),((¯1*~2|n)×n⍴2),z←⌽∊(¯1*2|⍳n)ר1,((⍳(n←.5×⍎⍞)-1)⍴¨2),¨1⋄(∊(((¯2↑¨'0',¨⍕¨n),¨⊂'To'),¨(¯2↑¨'0',¨⍕¨n-z)),¨⊂'|')~' '

Хорошая треть кода занимает форматирование вывода. Логика завершена появлением символа in в коде.

Ниже приведен результат для ввода 08 в качестве проверки:

04To05|06To04|07To06|05To07|03To05|02To03|04To02|06To04|08To06|09To08|07To09|05To07|03To05|01To03|02To01|04To02|06To04|08To06|07To08|05To07|03To05|04To03|06To04|05To06|
Грэхем
источник
1
Я всегда чувствую, что APL обманывает>. <
Shmiddty
@Shmiddty Я боюсь, что любой чисто символьный язык, такой как APL, J, GolfScript и т. Д., Скорее всего, выиграет кодовый гольф против более многословных языков, основанных на словах;)
Грэм
3

Javascript 178 174 161

prompts для nтогда alerts ответа. (Без 0заполнения)

Самый последний:

t=1+(m=prompt(s=i='')/2);for(z=Math.abs;i++<m*2;)for(j=m-z(m-i),s+=(t+=a=(m%2^z(m+.5-i)%2-.5)*-2+1)+'To'+(t-a)+'|';j--;)s+=(t+=a=i%2*4-2)+'To'+(t-a)+'|';alert(s)

2:

z=Math.abs;t=m=prompt(o=[])/2;t++;for(s=i='';i++<m*2;)for(j=m-z(m-i),o.push((z(m+.5-i)%2-.5)?-1:1);j--;)o.push(i%2?2:-2);o.map(function(a){s+=(t+=a)+'To'+(t-a)+'|'});alert(s)

1:

t=m=prompt(o=[])/2+1;for(s=i='';++i<m;)for(j=i,o.push(i%2?-1:1);j--;)o.push(i%2?2:-2);o.concat(o.slice().reverse().slice(m-1)).map(function(a){s+=(t+=a)+'To'+(t-a)+'|'});alert(s)

Это использует концепцию, что образец отражен:

Key
R='Jump Right'
r='Shift Right'
L='Jump Left'
l='Shift Left'
m='Move'
j='Jump'

Итак, где n=2, модель движения:

rLr
mjm

Что приравнивается к

+1 -2 +1

Этот шаблон повторяется как так ( n=8)

rLlRRrLLLlRRRRlLLLrRRlLr
mjmjjmjjjmjjjjmjjjmjjmjm
+1 -2 -1 +2 +2 +1 -2 -2 -2 -1 +2 +2 +2 +2 -1 -2 -2 -2 +1 +2 +2 -1 -2 +1

Мы можем заметить несколько моделей здесь:

  1. Движение чередуется между левым и правым
  2. Количество движений в определенном направлении увеличивается от 1 до n/2, которое повторяется 3 раза, а затем уменьшается до 1.
  3. Тип движения чередуется между смещением и прыжком, число сдвигов в ряду является постоянным 1, а количество последовательных прыжков увеличивается от 1 до n/2затем уменьшается до 1.
  4. Сумма движений всегда равна 0. (Не уверен, действительно ли это актуально)

n=14:

rLlRRrLLLlRRRRrLLLLLlRRRRRRrLLLLLLLrRRRRRRlLLLLLrRRRRlLLLrRRlLr
mjmjjmjjjmjjjjmjjjjjmjjjjjjmjjjjjjjmjjjjjjmjjjjjmjjjjmjjjmjjmjm

Пример вывода:

f(2):

1To2|3To1|2To3| 

f(8):

4To5|6To4|7To6|5To7|3To5|2To3|4To2|6To4|8To6|9To8|7To9|5To7|3To5|1To3|2To1|4To2|6To4|8To6|7To8|5To7|3To5|4To3|6To4|5To6|

f(40):

20To21|22To20|23To22|21To23|19To21|18To19|20To18|22To20|24To22|25To24|23To25|21To23|19To21|17To19|16To17|18To16|20To18|22To20|24To22|26To24|27To26|25To27|23To25|21To23|19To21|17To19|15To17|14To15|16To14|18To16|20To18|22To20|24To22|26To24|28To26|29To28|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|12To13|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|31To30|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|10To11|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|33To32|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|8To9|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|35To34|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|6To7|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|37To36|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|4To5|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|39To38|37To39|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|3To5|2To3|4To2|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|40To38|41To40|39To41|37To39|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|3To5|1To3|2To1|4To2|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|40To38|39To40|37To39|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|3To5|4To3|6To4|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|38To36|37To38|35To37|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|5To7|6To5|8To6|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|36To34|35To36|33To35|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|7To9|8To7|10To8|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|34To32|33To34|31To33|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|9To11|10To9|12To10|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|32To30|31To32|29To31|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|11To13|12To11|14To12|16To14|18To16|20To18|22To20|24To22|26To24|28To26|30To28|29To30|27To29|25To27|23To25|21To23|19To21|17To19|15To17|13To15|14To13|16To14|18To16|20To18|22To20|24To22|26To24|28To26|27To28|25To27|23To25|21To23|19To21|17To19|15To17|16To15|18To16|20To18|22To20|24To22|26To24|25To26|23To25|21To23|19To21|17To19|18To17|20To18|22To20|24To22|23To24|21To23|19To21|20To19|22To20|21To22|

Вот некоторый псевдокод для демонстрации метода:

var mid=cursor=N/2,delta
cursor++                 // the cursor is where the empty space is.
for(i=0; i++<N;){
  delta = (mid%2^abs(mid+.5-i)%2-.5)*-2+1;  // 1 or -1
  print((cursor+delta) + 'To' + cursor + '|')
  cursor+=delta
  for(j=mid-abs(mid-i);j--;)
  {
    delta = i%2*4-2  // 2 or -2
    print((cursor+delta) + 'To' + cursor + '|')
    cursor+=delta
  }
}
Shmiddty
источник
2
Вы правы в том, что шаблон более понятен с l/L/r/Rи m/j. Мне нравится идея разделения расстояния, перемещенного от направления
Гордон Бэйли
2

С - 216 213

Мое решение основано на двух фактах:

  1. Поле «to» - это поле «from» предыдущего хода (поскольку вы всегда создаете пустую ячейку в пространстве, из которого перемещаетесь, и вы всегда перемещаетесь в пустую ячейку)

  2. Существует очень регулярный образец расстояний и направлений, которые перемещаются. Для первых 3 тестовых случаев это:

    1 -2 1

    1 -2 -1 2 2 -1 -2 1

    1 -2 -1 2 2 1 -2 -2 -2 1 2 2 -1 -2 1

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

#include <stdio.h>

int main(int argc, const char *argv[])
{
   int upper_bound = atoi(argv[1]) / 2;
   int len;
   int from;
   int to = upper_bound + 1;
   int direction = 1;
   int i;

   for(len = 1; len <= upper_bound; ++len){
      for(i = len-1; i >=0; --i){
         from = to - direction*(1 + (i!=0));
         printf("%02dTo%02d|",from,to);
         to = from;
      }
      direction*=-1;
   }
   for(i=1; i < len; ++i){
      from = to - direction*2;
      printf("%02dTo%02d|",from,to);
      to = from;
   }
   direction*=-1;
   for(--len; len >= 0; --len){
      for(i = 0; i < len; ++i){
         from = to - direction*(1 + (i!=0));
         printf("%02dTo%02d|",from,to);
         to = from;
      }
      direction*=-1;
   }
   return 0;
}

И игра в гольф (хотя это был вызов, а не гольф):

#define B {F=T-D*(1+(i!=0));printf("%02dTo%02d|",F,T);T=F;}D*=-1;
L,F,T,D,i;main(int U,char**A){U=atoi(A[1])/2;T=U+1;D=1;for(L=1;L<=U;++L){for(i=L-1;i>=0;--i)B}for(i=1;i<L;++i)B for(--L;L>=0;--L){for(i=0;i<L;++i)B}}

#define B {F=T-D*(1+(i!=0));printf("%02dTo%02d|",F,T);T=F;}D*=-1;
L,F,T,D,i;main(int U){scanf("%d",&U);U/=2;T=U+1;D=1;for(L=1;L<=U;++L){for(i=L-1;i>=0;--i)B}for(i=1;i<L;++i)B for(--L;L>=0;--L){for(i=0;i<L;++i)B}}
Гордон Бейли
источник
Когда я запускаю вашу версию для гольфа, у меня возникает ошибка.
artistoex
Извините, я забыл упомянуть, что входные данные задаются в качестве аргумента командной строки - если вы запустите их без аргументов, это приведет к segfault. Но на самом деле теперь, когда вы упомянули это, я не знаю, почему я думал, что аргументы командной строки будут короче, чем scanf. Я обновляю свой ответ лучшей версией.
Гордон Бейли
Картина более заметен при использовании L / R / L / R (большой существо "скачок"): N(2)=rLr, N(4)=rLlRRlLr, N(6)=rLlRRrLLLrRRlLrи т.д.
Shmiddty
2

Mathematica

Этот подход строит Nestпоследовательность ed размера и направления ходов, отформатированную {fromPosition,toPosition}, начиная с позиции n, где nотносится к числу пар совпадений. Затем Foldпоследовательность превращается в функцию, которая начинается с перемещения {n, n+1}.

z@n_:=(p=1;h@t_:=Append[{Table[2 (-1)^t,{t}]},{(-1)^(t+1)}];
k=Join[Reverse@Drop[#,n],#]&[Flatten@Nest[Prepend[#,h[p++]]&,{},n]];
Fold[Append[#,{#[[-1,1]]-#2,#[[-1,1]]}]&,{{n,n+k[[1]]}},Rest@k])

z[1]

{{1, 2}, {3, 1}, {2, 3}}


z[4]

{{4, 5}, {6, 4}, {7, 6}, {5, 7}, {3, 5}, {2, 3}, {4, 2}, {6, 4}, { 8, 6}, {9, 8}, {7, 9}, {5, 7}, {3, 5}, {1, 3}, {2, 1}, {4, 2}, {6, 4}, {8, 6}, {7, 8}, {5, 7}, {3, 5}, {4, 3}, {6, 4}, {5, 6}}


z[7]

{{7, 8}, {9, 7}, {10, 9}, {8, 10}, {6, 8}, {5, 6}, {7, 5}, {9, 7}, { 11, 9}, {12, 11}, {10,12}, {8, 10}, {6, 8}, {4, 6}, {3, 4}, {5, 3}, {7, 5}, {9, 7}, {11, 9}, {13, 11}, {14, 13}, {12, 14}, {10, 12}, {8, 10}, {6, 8} , {4, 6}, {2, 4}, {1, 2}, {3, 1}, {5, 3}, {7, 5}, {9, 7}, {11, 9}, { 13, 11}, {15, 13}, {14, 15}, {12, 14}, {10, 12}, {8, 10}, {6, 8}, {4, 6}, {2, 4}, {3, 2}, {5, 3}, {7, 5}, {9, 7}, {11, 9}, {13, 11}, {12, 13}, {10, 12} , {8, 10}, {6, 8}, {4, 6}, {5, 4}, {7, 5}, {9, 7}, {11, 9}, {10, 11}, { 8, 10}, {6, 8}, {7, 6}, {9, 7}, {8, 9}}


Визуализация свопов

r, bи oявляются изображениями или красным соответствием, синим соответствием и отсутствием совпадения соответственно.

Матчи

Следующие данные форматируют вывод zдля отображения свопов со совпадениями.

swaps[n_]:=FoldList[Grid[{Permute[#[[1,1]],Cycles[{#2}]],Range[2n+1]}]&,
Grid[{Join[Table[r,{n}],{o},Table[b,{n}]],Range[2n+1]}],z[n]]

swapMatches[n_]:=Grid[Partition[swaps[n],2,2,1,""],Dividers->All]

swapsсоздает список состояний, используя упорядоченные пары zкоманд as для изменения начального и последующих списков.

swaps[1]

swaps1

swapMatches отображает состояния в сетке.

swapMatches[2]

swaps2

swapMatches[3]

swaps3

DavidC
источник
0

Javascript 191

function f(N) {
    n=N>>=i=c=a='1';n++
    s=z='0'
    for(k=b='34';i<N;k=i%2?a+=z+z:b+='44',i++)c=k+c
    t=''
    i=N*(N+1)/2
    l=2*i+N
    for(;l;n+=(i>=1?r=c[i-1]:i<=-N?c[-i-N]:k[1])-2,t+=(s=n>9?'':z)+n+a+'|',--l,--i)a='To'+s+n
    return t
}

Персонажи, подсчитанные с использованием grep =|tr -d \ |wc -c

artistoex
источник
1
Привет и добро пожаловать в Codegolf! Я думаю, вы обнаружите, что ваше решение не дает правильного вывода ни для одного из тестовых случаев ( jsfiddle.net/SJwaU ). Для ввода 02значения верны, но в конце отсутствует трейлинг |. В двух других случаях значения не соответствуют действительности, и форматирование 10также неверно. Также не уверен насчет вашего метода подсчета символов. Почему вы считаете только тело функции минус возврат?
Гордон Бейли
@gordon Упс, похоже, я допустил ошибку в своей последней оптимизации. Спасибо за указание. Я считаю тело только потому, что на REPL, это все, что вам нужно. Я поставил функцию украшения только для удобства.
artistoex
Вам нужно посчитать соответствующие пробелы (например, новые строки) к вашему общему количеству.
Шмиддты
@shmiddty tr -d \ |wc -cучитывает переводы строк
artistoex