Перетворіть 1 у будь-яке додатне ціле число, використовуючи лише операції * 3 та / 2


11

Будь-яке додатне ціле число можна отримати, починаючи з 1 і застосовуючи послідовність операцій, кожну з яких або "помножити на 3", або "ділити на 2, відкинувши будь-який залишок" .

Приклади (написання f для * 3 і g для / 2):

4 = 1 *3 *3 /2 = 1 ffg
6 = 1 ffggf = 1 fffgg
21 = 1 fffgfgfgggf

Напишіть програму з такою поведінкою:

Введення : будь-яке додатне ціле число, через stdin або жорстко закодоване. (Якщо жорстко закодовано, вхідна цифра буде виключена з програмної довжини.)
Вихід : рядок f і g такий, що <input> = 1 <string>(як у прикладах). Така рядок у зворотному порядку також прийнятна. Примітка: Вихід містить лише f і g, або порожній.

Виграш - запис із найменшими байтами програми плюс-вихід, коли 41 - це вхід.


1
Звідки ти знаєш, що це правда?
марін

@marinus вважається, що це правда (але ще не доведено). шукаючи доказів.
Fabinout

@marinus, ви можете довести, що це можливо шляхом спуску (або рівнозначно сильною індукцією). Розділення на регістр x mod 3: якщо x=3yпобудувати y, а потім застосувати f; якщо x=3y+1побудувати 2y+1та застосувати fтоді g; якщо x=3y+2тоді це ускладнюється, але по суті є рекурсивним.
Пітер Тейлор

На окремій ноті, чи має виведення бути у порядку подання заявки чи чи буде також прийнятний порядок композиції?
Пітер Тейлор

@PeterTaylor Так чи інакше.
res

Відповіді:


3

GolfScript, оцінка 64 (43-2 + 23)

0{)1.$2base:s{{3*}{2/}if}/41=!}do;s{103^}%+

(41 є жорстким кодом, тому -2 символи для оцінки). Вихід є

fffgffggffggffgggffgggg

що становить 23 символи (без нового рядка). Побудова коду гарантує, що він завжди повертає (одне) найкоротші уявлення.


Цитуючи користувача Даррена Стоун у запропонованій редакції на цій публікації: "Я не можу залишити тут коментар, тому я залишу редагування. Цей висновок не включає в себе перші два символи" 1 ", а також не відображені в балах. легке виправлення та все ще неймовірно коротке рішення. Привіт! " (Я відхилив, але подумав, що повинен перенести повідомлення)
Doorknob

@Doorknob У виклику зазначено, що "1 "не слід включати у висновок.
Говард

3

Ми бруднимось, друзі!

JAVA 210 207 199 символів

public class C{public static void main(String[] a){int i=41;String s="";while(i>1){if(i%3<1){s+="f";i/=3;}else if(i%3<2){s+="g";i+=i+1;}else{s+="g";i+=i+(Math.random()+0.5);}}System.out.println(s);}}

не гольф:

public class C {

    public static void main(String[] a) {

        int i = 41;
        String s = "";
        while (i > 1) {
            if (i % 3 == 0) {
                s += "f";
                i /= 3;
            } else {
                if (i % 3 == 1) {
                    s += "g";
                    i += i + 1;
                } else {
                    s += "g";
                    i += i + (Math.random() + 0.5);
                }
            }
        }
        System.out.println(s);
    }
}

вихід: залежно від віри старих богів, найкоротшим у мене було 30. Зверніть увагу, що вихід повинен читатися праворуч.

234

1 ggfgfgfgfggfggfgffgfggggfgffgfggfgfggggfgffgfggfgfggfgfggfgfgggggfffgfggfgfggfgfgggffgggggfffgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggfgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggggggggggggfgfgfggggfgfgfggfffgfgfggffgfgfggfgfggggffgfgfffff

108

1 gggffgfgfggggggfggggfgffggggfgfgfgfgfgffgggfgggggfggfffggfgfffffgggffggfgfgggffggfgfgggffggggggfgfgffgfgfff

редагувати 45

1 ggfgfgfgfgggfggfffgfggfgfgggggggffgffgfgfff

бали: 318 199 + 30 = 229

edit1 (2 * i + 1)% 3 == 0 -> (2 * i)% 3 == 1

Nota Bene, якщо під час гольфу ви використовуєте Java 6, а не Java 7, ви можете використовувати

public class NoMain {
    static {
        //some code
        System.exit(1);
    }
}

39 символів структурують замість стандартної структури довжиною 53 символи.


(2*i+1)%3==0еквівалентноi%3==1
Говард

Так. дякую
Fabinout

if(X){A}else{if(Y){B}else{C}}довше, ніж if(X){A}else if(Y){B}else{C}. Також ви можете замінити свої ==умови на більш короткі <.
Пітер Тейлор

@PeterTaylor правда, моє рішення все ще неприємне. Я не знаю, чи випадкова частина робить код коротшим, але це, безумовно, робить висновок crappier.
Fabinout

Ваші рядки f / g починаються з 'g' (що має означати '/ 2'), тому вони перетворять 1 на 0 замість 41. Зміна значень f до g та навпаки, також не здається дати 41.
res

3

Пітон, оцінка 124 (90-2 + ​​36)

x=41;m=f=g=0
while(3**f!=x)*(m!=x):
 f+=1;m=3**f;g=0
 while m>x:m/=2;g+=1
print'f'*f+'g'*g

90 символів коду (нові рядки по 1 у кожному) - 2 для жорстко закодованої цифри введення + 36 символів виводу

Вихід:

ffffffffffffffffgggggggggggggggggggg

1
Якщо це зробити, m=f=0ви можете зробити зовнішню петлю while(n!=x)*(m!=x)і усунути розриви. Подає це 95 символів коду.
Даніель Любаров

@Daniel: Ви, пане, пан і науковець. Дякую! Ваше подання все ще безпечно на 10 годин попереду мене. :)
Даррен Стоун

1
Ви можете додатково трохи заощадити, якщо замінити все nна 3**f.
Говард

1
Для введення = 1, ваша програма генерує помилку ("ім'я" g "не визначено", через те, що він не входить у зовнішній цикл while).
res

1
Ви можете вирізати іншого персонажа, написавши print'f'*f+'g'*g, що дало б оцінку 90-2 + ​​36 = 124.
res

3

Пітон, оцінка 121 (87 - 2 + 36)

t=bin(41)
l,n,f=len(t),1,0
while bin(n)[:l]!=t:f+=1;n*=3
print(len(bin(n))-l)*'g'+f*'f'

@Darren, я не знав, як інтерпретувати вихідний опис, але ви, мабуть, праві. Я додав '1'. Дякую!
Даніель Любаров

1
Ви можете кинути "1" (знову ж таки). Ваша оригінальна інтерпретація опису виводу була правильною. Насолоджуйтесь провідником Python знову! :-)
Даррен Стоун

1
Якщо ви об'єднали 2-й, 3-й та 4-й рядки в l,n,f=len(t),1,0та вилучили '1',з заяви про друк, ваш рахунок складе 87-2 + 36 = 121.
res

Спасибі хлопці - я кинув 1,. l,n,f=len(t),1,0дає однакову кількість символів, правда? (Для кожної змінної а =та новий рядок замінюються двома ,с.)
Даніель Любаров

Якщо кожен новий рядок має один символ (наприклад, LF у стилі UNIX), то однолінійна та трирядкова версії мають однакову довжину. Якщо кожен новий рядок має два символи (наприклад, CR + LF у стилі MS Windows), то однолінійна версія на два символи коротша, ніж трирядкова версія. Оцінка 121 передбачає односимвольні рядки.
res

1

Perl, оцінка 89 (63 - 2 + 28)

$_=41;$_=${$g=$_%3||$_==21?g:f}?$_*2+$_%3%2:$_/3while$_>print$g

Концепція: Якщо наївний підхід, описаний у моєму початковому рішенні нижче, коли-небудь досягне циклу, цей цикл буде [21, 7, 15, 5, 10, 21, ...] . Оскільки для 1 ≤ n ≤ 10 6 немає зустрічних прикладів, це, мабуть, є правдою. Щоб довести це, достатньо було б показати, що це єдиний цикл, який може існувати, який я можу зробити або не зробити в більш пізній момент часу.

Вищевказане рішення уникає циклу негайно, замість того, щоб здогадуватися (неправильно) та уникати його вдруге.

Вихід (28 байт):

ggfgfgfgfggfggfgfgfggfgfgfff

Perl, оцінка 100 (69 - 2 + 33)

$_=41;1while$_>print$s{$_=$$g?$_*2+$_%3%2:$_/3}=$g=$_%3||$s{$_/3}?g:f

Використання підходу для відгадки та перевірки. Рядок будується за допомогою обернених операцій (перетворення значення в 1 , а не навпаки), і рядок стає відображеним відповідно, що дозволено специфікацією проблеми.

Щоразу, коли трапляється не кратне три, воно буде помножено на два, додавши одне, якщо результат був би кратним три. Якщо зустрічається кратне три, воно ділиться на три ... якщо раніше це значення не зустрічалося, що вказує на цикл, отже, відгадка та перевірка.

Вихід (33 байти):

ggfgfgfgfggfggfgffgfgggfggfgfgfff

1

J, оцінка 103 (82-2 + 23)

* Примітка: я назвав свої дієслова fі g, не плутати з вихідними рядками fта g.

Твердо кодовані:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
'gf'{~#:(>:^:(41&~:@f@#:)^:_)1

Загальні функції:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
g=:3 :'''gf''{~#:(>:^:(y&~:@f@#:)^:_)1'

Усунули роботу з блоками двійкових чисел, що було найважливішою зміною, що стосується ущільнення g. Перейменовував змінні та видаляв пробіл для біса, але функціонально все одно. (Використання: g 41)

J, оцінка 197 (174 + 23)

f =: 3 : 0
acc =. 1
for_a. y do. acc =. ((*&3)`(<.&-:)@.a) acc end.
)

g =: 3 : 0
f2 =: f"1 f.
l =. 0$0
i =. 1
while. 0=$(l=.(#~(y&=@:f2))#:i.2^i) do. i=.>:i end.
'fg'{~{.l
)

Вихід: ffffffffggggggggfgffggg

fперетворює список булів у число, використовуючи 0s як *3і 1s як /2floor). #:i.2^iстворює масив 2-го рангу, що містить усі булеві масиви рангів 1 i.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.