Передаточные числа лего


23

Я строю гигантского робота Lego, и мне нужно сгенерировать некоторые конкретные передаточные числа, используя набор передач. У меня много передач с общими размерами лего: 8, 16, 24 или 40 зубьев. Напишите программу, которую я могу использовать, где я вводю передаточное число, и программа говорит мне, какую комбинацию шестерен я должен использовать, чтобы получить требуемое передаточное число.

Отношение ввода будет указано на стандартном вводе (или эквиваленте вашего языка) с двумя целыми числами, разделенными двоеточием. Соотношение a:bозначает, что выходной вал должен вращаться a/bтак же быстро, как и входной вал.

Вывод в стандартный вывод должен быть отдельной строкой, содержащей разделенный пробелами список передаточных чисел, в виде x:yгде x- размер шестерни на входном валу и yразмер шестерни на выходном валу. Вы должны использовать минимально возможное количество передач для данного передаточного числа. Каждый xи yдолжен быть одним из 8,16,24,40.

Примеры:

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

Если желаемое передаточное число невозможно, выведите «Невозможно». Если никаких передач не требуется, выведите пустую строку.

Это код гольф, самый короткий ответ выигрывает.


Разве соотношение зубов обратно пропорционально угловой скорости? Так, например, если желаемая скорость на входе равна 1: 5, не должно ли соотношение быть 40: 8 вместо 8:40? Или левостороннее отношение - эффективное соотношение зубьев зубчатого колеса к фактическому зубчатому колесу, которое вы хотите?
DavidC

Интересный вопрос ... 1:5 -> 8:40и 10:1 -> 40:8имеет смысл, но другие не так много.
Роб

@DavidCarraher: Полагаю, вы можете определить это любым способом. Я пытался быть внутренне последовательным. 1:5означает, что выходной вал вращается в 5 раз медленнее, и на этом происходит 8-зубчатая передача на входе и 40-зубчатая передача на выходе.
Кит Рэндалл

@MikeDtrick: ну, 10:1 -> 40:8 16:8не то, что ты сказал. Что насчет других смущает вас? 9:4реализован, делая 3:2дважды. 3:2реализуется с помощью 24:16.
Кит Рэндалл

2
@MikeDtrick: Да, на ваш первый вопрос. Чтобы получить 10: 1, вы можете сделать 5: 1 (используя 40 зубов / 8 зубов), а затем 2: 1 (используя 16 зубов / 8 зубов). 7:7так же, как 1:1, так что не требует никаких механизмов для реализации.
Кит Рэндалл

Ответы:


4

Питон - 204

Хорошо, я пойду первым:

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]
редактировать:

Чтобы «оптимизировать» вывод, это можно добавить перед printоператором,

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

доведя общее количество до 266 символов , я считаю.


1
<1можно заменить ==0. Также if b:a=...return aможет быть return b and...or a.
Угорен

Не работает, например, для 23:12.
Кит Рэндалл

Хорошо подмечено. Это проходит, так как 12 делится. Добавление elif i!=1:return[]к оригиналу решает проблему, но вводит другую. $ python gears.py <<< 21:28=> 24:16.. Я собираюсь разобраться в этом. Похоже, что проблема была не так проста: D Я думаю, что код должен быть еще длиннее, или мне нужен другой подход.
Даньеро

Вот и вы; Я думаю, что этот работает как ожидалось. Даже сделал его меньше :)
Daniero

Выглядит довольно хорошо, но это не оптимально. 6:15может быть сделано, 16:40но ваш код возвращается 24:40 16:24.
Кит Рэндалл

4

Perl - 310 306 294 288 272

Я немного заржавел с Perl и никогда не занимался гольф-кодом ... но никаких оправданий. Счетчик символов без разрывов строки. Использование 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"

Я с нетерпением жду критиков и намеков. Не так просто найти советы и рекомендации по коду-гольфу (в Perl).


Вы можете сохранить 9 символов, удалив $1:$2 -> , это не требуется в выводе.
DaveRandom

О, я неправильно понял спецификацию. Спасибо.
Патрик Б.

Вы можете уменьшить количество заявлений, например, $a[$_]=8 if!$a[$_];до$a[$_]||=8;
ardnew

Новые строки считаются одним символом.
Timtech

Первая строка может быть сокращена до ($v,$n)=split/:|\s/,<>;(не проверено).
msh210

2

swi-prolog, 324 250 248 204 байта

Пролог неплохо справляется с такой проблемой.

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.

Ввод передается как параметр-термин для предиката m. Вывод записывается в стандартный вывод. Извините за конечный «правда»; это просто способ переводчика, чтобы я знал, что все в порядке.

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

?- m(7:7).
true.

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

2

C, 246 216 213 байтов

В (бесполезной) попытке побить моё собственное решение Prolog, я полностью переписал решение 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);}

Мое оригинальное решение C (246 байт):

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

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


2

Pyth, 101 байт

(Почти наверняка неконкурентоспособен в конкурсе, поскольку использует язык более новый, чем сентябрь / 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\ 

Реализация @daniero 'python answer, но полуоптимизированная для 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

Попробуй здесь

Или проверить каждый случай


0

ES6, 230 байт

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

Один из моих самых длинных гольфов, так что я, должно быть, сделал что-то не так ... 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(" ");
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.