Trocando números [fechado]

10

Este é um quebra-cabeça comum que muitos de vocês resolveram manualmente. Agora é a hora de escrever um algoritmo para resolver o mesmo.

Existem palitos de igual número alinhados em dois lados diferentes, um de frente para o outro. Há um único espaço vazio entre eles. Diga algo como a figura a seguir (se o número total de palitos de fósforo for 4).

insira a descrição da imagem aqui

Cada bastão pode deslizar um passo na direção para a frente (se o espaço frontal imediato estiver livre) ou pode ser saltado sobre um bastão na frente e aterrissar no espaço livre (se esse espaço estiver livre). O movimento na direção inversa não é possível (até o espaço é livre). Nenhum salto reverso também é permitido. Apenas um movimento é permitido em uma etapa.

Agora, você deve escrever um algoritmo para encontrar as etapas mínimas necessárias, usando as palitos de fósforo do lado esquerdo para o lado direito e os palitos de fósforo do lado direito para o lado esquerdo.

Por exemplo: se houver um total de 2 palitos de fósforo (1 em cada lado), as etapas serão:

insira a descrição da imagem aqui

Nota: Na figura acima, o lado esquerdo foi movido primeiro. Existe outra solução quando o manípulo do lado direito se move primeiro. Mas para esse problema, você deve fornecer apenas uma solução e isso também pressupondo que o manípulo do lado esquerdo se mova primeiro.

A figura a seguir descreve os movimentos com 4 palitos de fósforo (2 de cada lado):

insira a descrição da imagem aqui

Nota: Na figura acima, o lado esquerdo foi movido primeiro. Existe outra solução quando o manípulo do lado direito se move primeiro. Mas para esse problema, você deve fornecer apenas uma solução e isso também pressupondo que o manípulo do lado esquerdo se mova primeiro.

[Suposição: A entrada pode ser qualquer número par entre 02 e 14 (ou seja, 1 a 7 palitos de fósforo em cada lado). Para entradas fora desse intervalo, você não precisa fazer nenhuma validação nem fornecer nenhuma mensagem de erro. Nota: Na saída, cada etapa é separada por um '|' caractere (pipe). Os programadores COBOL sempre devem assumir o PIC 9 (2) como tamanho de entrada e também podem assumir que a saída tenha comprimento máximo fixo de 450 caracteres, preenchido com espaços à direita.]


Entrada de amostra:

02  

Saída de amostra:

01To02|03To01|02To03|


Entrada de amostra:

04  

Saída de amostra:

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


Entrada de amostra:

06  

Saída de amostra:

03To04|05To03|06To05|04To06|02To04|01To02|03To01|05To03|07To05|06To07|04To06|02To04|03To02|05To03|04To05|
user2076421
fonte
Se você não pode incluir as imagens diretamente, pode fornecer links para outra pessoa editá-las?
Peter Taylor
2
Eu fiz algumas imagens rápidas. Espero que eles estejam de acordo com a intenção do autor original.
primo
3
Condição para a vitória?
Shmiddty

Respostas:

3

APL 129

O código abaixo leva a entrada e a saída da tela para a tela no formato especificado:

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)),¨⊂'|')~' '

Um bom terço do código é utilizado para formatar a saída. A lógica é completa pela ocorrência do símbolo in no código.

Abaixo está o resultado para uma entrada 08 como uma verificação:

04To05|06To04|07To06|05To07|03To05|02To03|04To02|06To04|08To06|09To08|07To09|05To07|03To05|01To03|02To01|04To02|06To04|08To06|07To08|05To07|03To05|04To03|06To04|05To06|
Graham
fonte
11
Eu sempre sinto que o APL está trapaceando>. <
Shmiddty 21/02
@Shmiddty Tenho medo de que qualquer linguagem puramente símbolo baseado tais como APL, J, GolfScript etc provavelmente irá ganhar golf código contra mais detalhado linguagens baseadas palavra;)
Graham
3

Javascript 178 174 161

prompts para nentão alerts resposta. (Sem 0preenchimento)

Mais recentes:

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)

Isso usa o conceito de que o padrão é espelhado:

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

Então, onde n=2, o padrão de movimento é:

rLr
mjm

O que equivale a

+1 -2 +1

Esse padrão se repete assim ( 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

Podemos notar alguns padrões aqui:

  1. O movimento alterna entre esquerda e direita
  2. O número de movimentos em uma direção específica aumenta de 1 para n/2, que se repete 3 vezes e depois volta para 1.
  3. O tipo de movimento alterna entre deslocamento e salto, o número de turnos consecutivos sendo uma constante 1e o número de saltos sequenciais aumentando de 1 para n/2depois diminuindo de volta para 1.
  4. A soma dos movimentos é sempre 0. (Não tenho certeza se isso é realmente relevante)

n=14:

rLlRRrLLLlRRRRrLLLLLlRRRRRRrLLLLLLLrRRRRRRlLLLLLrRRRRlLLLrRRlLr
mjmjjmjjjmjjjjmjjjjjmjjjjjjmjjjjjjjmjjjjjjmjjjjjmjjjjmjjjmjjmjm

Saída de amostra:

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|

Aqui estão alguns pseudo-códigos para demonstrar o método:

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
fonte
2
Você está certo de que o padrão é mais claro com l/L/r/Re m/j. Eu gosto da idéia de separar a distância movida da direção
Gordon Bailey
2

C - 216 213

Minha solução é baseada em dois fatos:

  1. O campo "para" é o campo "de" da movimentação anterior (já que você sempre cria um espaço vazio no espaço do qual se move e sempre move para um espaço vazio)

  2. Existe um padrão muito regular para as distâncias e direções que são movidas. Para os três primeiros casos de teste, eles são:

    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

Com isso em mente, basicamente escrevi um programa para produzir e continuar esse padrão. Tenho certeza de que deve haver uma maneira recursiva muito bonita e muito mais elegante de escrever isso, mas ainda não descobri:

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

E jogava golfe (mesmo que esse fosse um desafio de código, não golfe):

#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}}
Gordon Bailey
fonte
Quando executo sua versão de golfe, recebo um segfault.
Artistoex
Ah, desculpe, esqueci de mencionar que a entrada é fornecida como um argumento de linha de comando - se você executá-la sem argumentos, ela falhará. Mas, na verdade, agora que você mencionou, não sei por que pensei que os argumentos da linha de comando seriam menores que scanf. Estou atualizando minha resposta com uma versão melhor.
Gordon Bailey
O padrão é mais perceptível quando você usa L / R / l / r (ser grande "salto"): N(2)=rLr, N(4)=rLlRRlLr, N(6)=rLlRRrLLLrRRlLr, etc.
Shmiddty
2

Mathematica

Essa abordagem cria uma Nestsequência ed do tamanho e da direção dos movimentos, formatada como {fromPosition,toPosition}, começando pela posição n, em que nse refere ao número de pares de correspondência. Em seguida, Foldé a sequência para uma função que começa com o movimento {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}}


Visualizando os Swaps

r,, be osão imagens ou uma correspondência vermelha, uma correspondência azul e nenhuma correspondência, respectivamente.

fósforos

A seguir, formata a saída de zpara exibir os swaps com correspondências.

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]

swapsproduz uma lista de estados usando os pares ordenados de zcomo comandos para permutar a lista inicial e as listas subseqüentes.

swaps[1]

swaps1

swapMatches exibe os estados em uma grade.

swapMatches[2]

swaps2

swapMatches[3]

swaps3

DavidC
fonte
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
}

Caracteres contados usando grep =|tr -d \ |wc -c

artistoex
fonte
11
Olá e bem-vindo ao codegolf! Acho que você descobrirá que sua solução não produz a saída correta para nenhum dos casos de teste ( jsfiddle.net/SJwaU ). Para a entrada 02, os valores estão corretos, mas está faltando o final |. Nos outros dois casos, os valores estão muito diferentes e a formatação de 10também está incorreta. Também não tem certeza sobre o seu método de contagem de caracteres. Por que você está contando apenas o corpo da função menos o retorno?
Gordon Bailey
@ordon Ops, parece que cometi um erro na minha otimização mais recente. Obrigado por apontar. Eu conto o corpo apenas porque em um REPL, é tudo o que você precisa. Coloquei a função decoração apenas por uma questão de conveniência.
Artistoex
Você precisa contar com espaço em branco relevante (por exemplo, novas linhas) no total.
Shmiddty
@shmiddty tr -d \ |wc -cleva novas linhas em conta
artistoex