Rapporti di cambio Lego


23

Sto costruendo un gigantesco robot lego e ho bisogno di generare alcuni rapporti di trasmissione particolari utilizzando una serie di ingranaggi. Ho un sacco di ingranaggi con le dimensioni degli ingranaggi lego comuni: 8, 16, 24 o 40 denti. Scrivi un programma che posso usare quando inserisco un rapporto di trasmissione e il programma mi dice quale combinazione di ingranaggi dovrei usare per ottenere il rapporto richiesto.

Il rapporto di input verrà specificato sull'input standard (o l'equivalente della tua lingua) con due numeri interi separati da due punti. Un rapporto a:bindica che l'albero di uscita deve ruotare i a/btempi più velocemente dell'albero di entrata.

L'output all'output standard dovrebbe essere una riga singola contenente un elenco separato da spazi di rapporti di trasmissione, nella forma in x:ycui si xtrova la dimensione dell'ingranaggio sull'albero di ingresso e yla dimensione dell'ingranaggio sull'albero di uscita. È necessario utilizzare il numero minimo possibile di marce per il rapporto indicato. Ognuno xe ydeve essere uno di 8,16,24,40.

esempi:

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 il rapporto di trasmissione desiderato è impossibile, stampare "IMPOSSIBILE". Se non è necessario alcun ingranaggio, stampare la stringa vuota.

Questo è il golf del codice, vince la risposta più breve.


Il rapporto tra i denti non è inversamente proporzionale alla velocità angolare? Quindi, ad esempio se la velocità di uscita in ingresso desiderata è 1: 5, il rapporto non dovrebbe essere 40: 8 anziché 8:40? Oppure il rapporto a sinistra è il rapporto tra i denti effettivi e quelli effettivi che desideri?
DavidC

Domanda interessante ... 1:5 -> 8:40e ha 10:1 -> 40:8un senso, ma gli altri non tanto.
Rob,

@DavidCarraher: immagino che tu possa definirlo in entrambi i modi. Ho cercato di essere coerente internamente. 1:5significa che l'albero di uscita gira 5 volte più lentamente, e un ingranaggio a 8 denti sull'ingresso e un ingranaggio a 40 denti sull'uscita lo fanno accadere.
Keith Randall,

@MikeDtrick: beh, 10:1 -> 40:8 16:8non quello che hai detto. E gli altri ti confondono? 9:4viene implementato facendo 3:2due volte. 3:2è implementato usando 24:16.
Keith Randall,

2
@MikeDtrick: Sì alla tua prima domanda. Per ottenere 10: 1 puoi fare 5: 1 (usando 40 denti / 8 denti) e poi 2: 1 (usando 16 denti / 8 denti). 7:7è uguale a 1:1, quindi non richiede attrezzi da implementare.
Keith Randall,

Risposte:


4

Python - 204

Ok, vado io per primo:

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]
modificare:

Per "ottimizzare" l'output, questo può essere aggiunto prima printdell'istruzione,

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

portando il totale fino a 266 personaggi , credo.


1
<1può sostituire ==0. Inoltre, if b:a=...return apuò essere return b and...or a.
ugoren,

Non funziona per es 23:12.
Keith Randall,

Ben individuato. Passa dal momento che 12 è divisibile. L'aggiunta elif i!=1:return[]all'originale risolve il problema ma ne introduce un altro. $ python gears.py <<< 21:28=> 24:16.. Lo esaminerò. Sembra che il problema non sia poi così semplice: DI Pensa che il codice debba essere ancora più lungo, o ho bisogno di un altro approccio.
daniero,

Ecco qua; Penso che questo funzioni come previsto. Anche reso più piccolo :)
daniero

Sembra abbastanza buono, ma non è ottimale. 6:15può essere fatto con 16:40ma il tuo codice ritorna 24:40 16:24.
Keith Randall,

4

Perl - 310 306 294 288 272

Sono un po 'arrugginito con Perl e non ho mai fatto un code-golf ... ma senza scuse. Il conteggio dei caratteri è senza interruzioni di riga. Utilizzando 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"

Non vedo l'ora di critiche e suggerimenti. Non è così facile trovare suggerimenti e trucchi per code-golf (in perl).


È possibile salvare 9 caratteri rimuovendoli $1:$2 -> , non è necessario nell'output.
DaveRandom,

Oh, ho letto male le specifiche. Grazie.
Patrick B.

È possibile ridurre le dichiarazioni come $a[$_]=8 if!$a[$_];ad$a[$_]||=8;
ardnew

Newline conta come un personaggio.
Timtech,

La prima riga può essere abbreviata in ($v,$n)=split/:|\s/,<>;(non testato).
msh210,

2

swi-prolog, 324 250 248 204 byte

Prolog fa abbastanza bene a risolvere un problema come questo.

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.

L'input viene passato come parametro di termine da predicare m. L'output viene scritto su stdout. Mi dispiace per il finale "vero"; questo è solo il modo dell'interprete di farmi sapere che tutto andava bene.

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

?- m(7:7).
true.

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

2

C, 246 216 213 byte

In un (inutile) tentativo di battere la mia soluzione Prolog, ho riscritto completamente la soluzione 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);}

La mia soluzione C originale (246 byte):

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

È stato un buon esercizio per dimostrare che può essere fatto senza costruire liste.


2

Pyth, 101 byte

(Quasi certamente non in competizione nel concorso in quanto utilizza una lingua più recente di settembre 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\ 

Un'implementazione della risposta python di @daniero ma semi-ottimizzata per 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

Provalo qui

O prova ogni caso


0

ES6, 230 byte

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` `)

Uno dei miei golf più lunghi, quindi devo aver fatto qualcosa di sbagliato ... 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(" ");
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.