Relações de engrenagem Lego


23

Estou construindo um robô lego gigante e preciso gerar algumas relações de engrenagem específicas usando um conjunto de engrenagens. Eu tenho muitas artes com os tamanhos comuns de artes lego: 8, 16, 24 ou 40 dentes. Escreva um programa que eu possa usar onde insira uma taxa de engrenagem e o programa me diga qual combinação de engrenagens devo usar para obter a taxa solicitada.

A taxa de entrada será especificada na entrada padrão (ou equivalente no seu idioma) com dois números inteiros separados por dois pontos. Uma proporção a:bsignifica que o eixo de saída deve girar a/bvezes mais rápido que o eixo de entrada.

A saída para saída padrão deve ser uma única linha que contém uma lista de relações de transmissão separada por espaço, na forma de x:yonde xé o tamanho da engrenagem no eixo de entrada e yo tamanho da engrenagem no eixo de saída. Você deve usar o número mínimo possível de marchas para a proporção especificada. Cada um xe ydeve ser um dos 8,16,24,40.

exemplos:

1:5 -> 8:40
10:1 -> 40:8 16:8
9:4 -> 24:16 24:16
7:1 -> IMPOSSIBLE
7:7 ->
6:15 -> 16:40

Se a relação de transmissão desejada for impossível, imprima "IMPOSSÍVEL". Se nenhuma engrenagem for necessária, imprima a corda vazia.

Este é o código de golfe, a resposta mais curta vence.


A proporção de dentes não é inversamente proporcional à velocidade angular? Então, por exemplo, se a velocidade de saída de entrada desejada for 1: 5, a proporção não deve ser 40: 8 em vez de 8:40? Ou a proporção da mão esquerda é a relação entre dentes da engrenagem efetiva e a quantidade real desejada?
DavidC

Pergunta interessante ... 1:5 -> 8:40e 10:1 -> 40:8faz sentido, mas os outros nem tanto.
Rob

@ DavidCarraher: Eu acho que você pode defini-lo de qualquer maneira. Eu tentei ser internamente consistente. 1:5significa que o eixo de saída gira 5 vezes mais devagar, e uma engrenagem de 8 dentes na entrada e uma engrenagem de 40 dentes na saída fazem isso acontecer.
Keith Randall

@ MikeDtrick: bem, 10:1 -> 40:8 16:8não o que você disse. E os outros confunde você? 9:4é implementado fazendo 3:2duas vezes. 3:2é implementado usando 24:16.
Keith Randall

2
@ MikeDtrick: Sim, para sua primeira pergunta. Para obter 10: 1, você pode fazer 5: 1 (usando 40 dentes / 8 dentes) e depois 2: 1 (usando 16 dentes / 8 dentes). 7:7é o mesmo que 1:1, portanto, não requer engrenagens para implementar.
amigos estão dizendo sobre keith

Respostas:


4

Python - 204

Ok, eu vou primeiro:

def p(n,a=[1]*9):
 n=int(n)
 for i in(2,3,5):
    while n%i<1:n/=i;a=[i]+a
 return a,n
(x,i),(y,j)=map(p,raw_input().split(':'))
print[' '.join(`a*8`+':'+`b*8`for a,b in zip(x,y)if a!=b),'IMPOSSIBLE'][i!=j]
editar:

Para 'otimizar' a saída, isso pode ser adicionado antes da printdeclaração,

for e in x:
 if e in y:x.remove(e);y.remove(e)

elevando o total até 266 caracteres , acredito.


1
<1pode substituir ==0. Além disso, if b:a=...return apode ser return b and...or a.
precisa saber é o seguinte

Não funciona para, por exemplo 23:12,.
amigos estão dizendo sobre keith

Bem manchado. Isso acontece porque 12 é divisível. A adição elif i!=1:return[]ao original resolve o problema, mas apresenta outro. $ python gears.py <<< 21:28=> 24:16.. eu vou investigar. Parece que o problema não era tão simples, afinal: DI Acho que o código precisa ser ainda mais longo ou preciso de outra abordagem.
Daniero 4/09/12

Ai está; Eu acho que este funciona como esperado. Mesmo tornou menor :)
daniero

Parece muito bom, mas não é o ideal. 6:15pode ser feito com, 16:40mas seu código retorna 24:40 16:24.
Keith Randall

4

Perl - 310 306 294 288 272

Estou um pouco enferrujado com perl e nunca joguei golfe de código ... mas não tenho desculpas. A contagem de caracteres é sem quebras de linha. Usando o perl v5.14.2.

($v,$n)=<>=~/(.+):(.+)/;
($x,$y)=($v,$n);($x,$y)=($y,$x%$y)while$y;
sub f{$p=shift;$p/=$x;for(5,3,2){
while(!($p%$_)){$p/=$_;push@_,$_*8}}
$o="IMPOSSIBLE"if$p!=1;
@_}
@a=f($v);@b=f($n);
if(!$o){for(0..($#b>$#a?$#b:$#a)){
$a[$_]||=8;
$b[$_]||=8;
push@_,"$a[$_]:$b[$_]"}}
print"$o@_\n"

Estou ansioso por críticas e sugestões. Não é tão fácil encontrar dicas e truques para o código-golfe (em perl).


Você pode salvar 9 caracteres removendo $1:$2 -> , não é necessário na saída.
DaveRandom

Ah, eu interpretei errado as especificações. Obrigado.
Patrick B.

Você pode reduzir declarações como $a[$_]=8 if!$a[$_];a$a[$_]||=8;
ardnew

As novas linhas contam como um caractere.
Timtech

A primeira linha pode ser abreviada para ($v,$n)=split/:|\s/,<>;(não testada).
Msh210

2

swi-prólogo, 324 250 248 204 bytes

Prolog faz muito bem em resolver um problema como este.

m(P):-(g(P,L),!;L='IMPOSSIBLE'),write(L).
g(A:A,''):-!.
g(A:B,L):-A/C/X,C>1,B/C/Y,!,g(X:Y,L);A/C/X,!,B/D/Y,C*D>1,g(X:Y,T),format(atom(L),'~D:~D ~a',[C*8,D*8,T]).
X/Y/Z:-(Y=5;Y=3;Y=2;Y=1),Z is X//Y,Y*Z>=X.

A entrada é passada como um parâmetro de termo para predicado m. A saída é gravada em stdout. Desculpe pelo "verdadeiro" à direita; essa é apenas a maneira do intérprete de me informar que estava tudo bem.

?- m(54:20).
24:40 24:16 24:8 
true.

?- m(7:7).
true.

?- m(7:1).
IMPOSSIBLE
true.

2

C, 246 216 213 bytes

Em uma tentativa (fútil) de vencer minha própria solução Prolog, reescrevi completamente a solução C.

b,c,d;f(a,b,p){while(c=a%5?a%3?a%2?1:2:3:5,d=b%5?b%3?b%2?1:2:3:5,c*d>1)c<2|b%c?d<2|a%d?p&&printf("%d:%d ",8*c,8*d):(c=d):(d=c),a/=c,b/=d;c=a-b;}main(a){scanf("%d:%d",&a,&b);f(a,b,0);c?puts("IMPOSSIBLE"):f(a,b,1);}

Minha solução C original (246 bytes):

#define f(c,d) for(;a%d<1;a/=d)c++;for(;b%d<1;b/=d)c--;
b,x,y,z;main(a){scanf("%d:%d",&a,&b);f(x,2)f(y,3)f(z,5)if(a-b)puts("IMPOSSIBLE");else
while((a=x>0?--x,2:y>0?--y,3:z>0?--z,5:1)-(b=x<0?++x,2:y<0?++y,3:z<0?++z,5:1))printf("%d:%d ",a*8,b*8);}

Foi um bom exercício para provar que isso pode ser feito sem criar listas.


2

Pitão, 101 bytes

(Quase certamente não concorrente no concurso, pois usa um idioma mais recente que set / 2012)

D'HJH=Y[)VP30W!%JN=/JN=Y+NY))R,YJ;IneKhm'vdcz\:J"IMPOSSIBLE").?V.t,.-Y.-hK=J.-hKYJ1In.*Npj\:m*8d_Np\ 

Uma implementação da resposta python do @daniero ', mas semi-otimizada para Pyth.

D'H                               - Define a function (') which takes an argument, H.
   JH                             - J = H (H can't be changed in the function)
     =Y[)                         - Y = []
         V                        - For N in ...
          P30                     - Prime factors of 30 (2,3,5)
             W!%JN                - While not J%N
                  =/JN            - J /= N
                      =Y+NY       - Y = N + Y
                           ))R,YJ - To start of function, return [Y,J]

ENDFUNCTION

If 
         cz\:  - Split the input by the ':'
     m'vd      - ['(eval(d)) for d in ^]
   Kh          - Set K to the first element of the map (before the :)
  e            - The second returned value
             J - The second returned value after the : (The variables are globals)
 n             - Are not equal

Then 
"IMPOSSIBLE" - Print "IMPOSSIBLE"

Else
V                                      - For N in
 .t                1                   - transpose, padded with 1's
             .-hKY                     - 1st function first return - 2nd function first return
           =J                          - Set this to J
       .-hK                            - 1st function first return - ^
    .-Y                                - 2nd function first return - ^
   ,              J                    - [^, J]
                                         (Effectively XOR the 2 lists with each other)
                    I                  - If
                     n.*N              - __ne__(*N) (if n[0]!=n[1])
                         pj\:m*8d_N    - print ":".join([`d*8` for d in reversed(N)])
                                   p\  - print a space seperator

Experimente aqui

Ou teste todos os casos


0

ES6, 230 bytes

x=>([a,b]=x.split`:`,f=(x,y)=>y?f(y,x%y):x,g=f(a,b),d=[],a/=g,f=x=>{while(!(a%x))a/=x,d.push(x*8)},[5,3,2].map(f),c=d,d=[],a*=b/g,[5,3,2].map(f),a>1?'IMPOSSIBLE':(c.length<d.length?d:c).map((_,i)=>(c[i]||8)+':'+(d[i]||8)).join` `)

Um dos meus campos mais longos, então eu devo ter feito algo errado ... Ungolfed:

x => {
    [a, b] = x.split(":");
    f = (x, y) => y ? f(y, x % y) : x; // GCD
    g = f(a, b);
    f = x => {
        r = [];
        while (!(x % 5)) { x /= 5; r.push(5); }
        while (!(x % 3)) { x /= 3; r.push(3); }
        while (!(x % 2)) { x /= 2; r.push(2); }
        if (x > 1) throw "IMPOSSIBLE!";
        return r;
    }
    c = f(a);
    d = f(b);
    r = [];
    for (i = 0; c[i] || d[i]; i++) {
        if (!c[i]) c[i] = 8;
        if (!d[i]) d[i] = 8;
        r[i] = c[i] + ":" + d[i];
    }
    return r.join(" ");
}
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.