Rapports de démultiplication Lego

23

Je construis un robot lego géant et j'ai besoin de générer des rapports de vitesse particuliers en utilisant un ensemble d'engrenages. J'ai beaucoup de vitesses avec les tailles d'engrenages lego courantes: 8, 16, 24 ou 40 dents. Écrivez un programme que je peux utiliser où je saisis un rapport d'engrenage et le programme me dit quelle combinaison de vitesses je dois utiliser pour obtenir le rapport demandé.

Le rapport d'entrée sera spécifié sur l'entrée standard (ou l'équivalent de votre langue) avec deux entiers séparés par deux points. Un ratio a:bsignifie que l'arbre de sortie doit tourner des a/btemps aussi rapides que l'arbre d'entrée.

La sortie vers la sortie standard doit être une seule ligne contenant une liste séparée par des espaces des rapports d'engrenage, sous la forme x:yxest la taille de l'engrenage sur l'arbre d'entrée et yest la taille de l'engrenage sur l'arbre de sortie. Vous devez utiliser le nombre minimum de vitesses possible pour le rapport donné. Chacun xet ydoit être l'un des 8,16,24,40.

exemples:

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

Si le rapport de vitesse souhaité est impossible, imprimez "IMPOSSIBLE". Si aucun engrenage n'est requis, imprimez la chaîne vide.

C'est le golf de code, la réponse la plus courte l'emporte.

Keith Randall
la source
Le rapport des dents n'est-il pas inversement proportionnel à la vitesse angulaire? Ainsi, par exemple, si la vitesse de sortie d'entrée souhaitée est de 1: 5, le rapport ne devrait-il pas être de 40: 8 au lieu de 8:40? Ou le rapport de gauche est-il le rapport entre les dents d'engrenage efficaces et les dents d'engrenage réelles que vous souhaitez?
DavidC
Question intéressante ... 1:5 -> 8:40et 10:1 -> 40:8logique, mais pas les autres.
Rob
@DavidCarraher: Je suppose que vous pouvez le définir de toute façon. J'ai essayé d'être cohérent en interne. 1:5signifie que l'arbre de sortie tourne 5 fois plus lentement, et un engrenage à 8 dents sur l'entrée et un engrenage à 40 dents sur la sortie rendent cela possible.
Keith Randall
@MikeDtrick: eh bien, 10:1 -> 40:8 16:8pas ce que vous avez dit. Et les autres vous déroutent? 9:4est implémenté en faisant 3:2deux fois. 3:2est implémenté à l'aide de 24:16.
Keith Randall
2
@MikeDtrick: Oui à votre première question. Pour obtenir 10: 1, vous pouvez faire 5: 1 (en utilisant 40 dents / 8 dents) puis 2: 1 (en utilisant 16 dents / 8 dents). 7:7est identique à 1:1, il ne nécessite donc aucun engrenage à implémenter.
Keith Randall

Réponses:

4

Python - 204

Ok, je vais commencer:

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

Pour «optimiser» la sortie, cela peut être ajouté avant la printdéclaration,

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

ce qui porte le total à 266 caractères , je crois.

daniero
la source
1
<1peut remplacer ==0. , Aussi if b:a=...return apeut être return b and...or a.
ugoren
Ne fonctionne pas pour, par exemple 23:12.
Keith Randall
Bien repéré. Il passe par puisque 12 est divisible. L'ajout elif i!=1:return[]à l'original résout le problème mais en introduit un autre. $ python gears.py <<< 21:28=> 24:16.. Je vais y jeter un œil. On dirait que le problème n'était pas si simple après tout: DI Je pense que le code doit être encore plus long, ou j'ai besoin d'une autre approche.
daniero
Voilà; Je pense que celui-ci fonctionne comme prévu. Même rendu plus petit :)
daniero
Semble assez bon, mais ce n'est pas optimal. 6:15peut être fait avec 16:40mais votre code revient 24:40 16:24.
Keith Randall
4

Perl - 310 306 294 288 272

Je suis un peu rouillé avec Perl et je n'ai jamais fait de golf de code ... mais pas d'excuses. Le nombre de caractères est sans saut de ligne. Utilisation de 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"

J'ai hâte de recevoir des critiques et des indices. Ce n'est pas si facile de trouver des trucs et astuces pour le code-golf (en perl).

Patrick B.
la source
Vous pouvez enregistrer 9 caractères en les supprimant $1:$2 -> , ils ne sont pas requis dans la sortie.
DaveRandom
Oh, j'ai mal lu la spécification. Merci.
Patrick B.
Vous pouvez réduire les déclarations comme $a[$_]=8 if!$a[$_];à$a[$_]||=8;
ardnew
Les sauts de ligne comptent comme un seul caractère.
Timtech
La première ligne peut être abrégée en ($v,$n)=split/:|\s/,<>;(non testé).
msh210
2

swi-prolog, 324 250 248 204 octets

Prolog réussit assez bien à résoudre un problème comme celui-ci.

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'entrée est transmise en tant que paramètre de terme au prédicat m. La sortie est écrite sur stdout. Désolé pour le «vrai» qui suit. c'est juste la façon dont l'interprète m'a fait savoir que tout allait bien.

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

?- m(7:7).
true.

?- m(7:1).
IMPOSSIBLE
true.
Ruud Helderman
la source
2

C, 246 216 213 octets

Dans une tentative (futile) de battre ma propre solution Prolog, j'ai complètement réécrit la solution 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);}

Ma solution C d'origine (246 octets):

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

C'était un bon exercice pour prouver que cela peut se faire sans construire de listes.

Ruud Helderman
la source
2

Pyth, 101 octets

(Presque certainement pas en compétition car il utilise une langue plus récente que sep / 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\ 

Une implémentation de la réponse python de @daniero mais semi-optimisée pour 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

Essayez-le ici

Ou testez chaque cas

Bleu
la source
0

ES6, 230 octets

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

Un de mes golfs les plus longs, donc j'ai dû faire quelque chose de mal ... 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(" ");
}
Neil
la source