Половина, Половина Половина і, Половина


33

Розглянемо таку послідовність чисел:

0,12,14,34,18,38,58,78,116,316,516,716,916,1116,1316,1516,132,332,532,

Він перераховує всі двійкові дроби в одиничному інтервалі .[0,1)

(Щоб полегшити цей виклик, перший елемент необов’язковий: ви можете пропустити його і вважати, що послідовність починається з 1/2.)

Завдання

Напишіть програму (повну програму або функцію), яка ...

Виберіть одну з таких форм поведінки:

  • Введення n, вихід n-го елемента послідовності (0-індексований або 1-індексований);
  • Введення n, вихід перших n елементів послідовності;
  • Нічого не вводьте, виведіть нескінченну послідовність чисел, яку ви можете взяти один за одним;

Правило

  • Ваша програма повинна підтримувати хоча б перші 1000 елементів;
  • Ви можете обрати десяткові знаки або дроби (вбудована ціла пара, рядки), як вам подобається;
    • Введення / вихід як двійкові цифри у цьому запиті заборонено;
  • Це , найкоротший виграш кодів;
  • Стандартні лазівки заборонені.

Тестові шафи

input output
1     1/2     0.5
2     1/4     0.25
3     3/4     0.75
4     1/8     0.125
10    5/16    0.3125
100   73/128  0.5703125
511   511/512 0.998046875
512   1/1024  0.0009765625

Ці приклади ґрунтуються на 0-індексованій послідовності з включеною першою 0. Вам потрібно буде відрегулювати вхід для відповідного рішення.

Детальніше

  • OEIS A006257
    • Завдання Йосифа: a2n=2an1,a2n+1=2an+1 . (Раніше M2216)
    • 0, 1, 1, 3, 1, 3, 5, 7, 1, 3, 5, 7, 9, 11, 13, 15, 1, 3, 5, ...
  • OEIS A062383
    • : при n > 0 , a n = 2 l o g 2 n + 1 або a n = 2 a na0=1n>0an=2log2n+1.an=2an2
    • 1, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, ...
  • A006257 (n) / A062383 (n) = (0, 0,1, 0,01, 0,11, 0,001, ...) перераховує всі двійкові дроби в одиничному інтервалі [0, 1). - Фредрік Йохансон, 14 серпня 2006 року


4
" Нічого не вводьте, виведіть нескінченну послідовність чисел по черзі " Це повинно бути по одному, чи нам також дозволено виводити нескінченний список (можливо в Haskell, Elixir, 05AB1E тощо)?
Кевін Круїйсен

Чи можу я вивести список рядків? наприклад"1/2" "1/4" "1/8"...
Barranka

@KevinCruijssen Нескінченний список чудовий, якщо ви зможете takeпізніше отримати елементи з нього.
tsh

@Barranka Я думаю, що це прийнятно. Це не відрізняється від друку фракцій до stdout.
тш

Коли ви говорите, що введення / вихід як бінарні числа не дозволені , ви маєте на увазі, що ми не можемо записати функцію, яка повертає пару if int, або a doubleв мові / реалізації, де doubleвикористовується формат IEEE binary64 ? Я сподіваюся, ви не маєте на увазі, чи потрібно було проаналізувати рядок ASCII, якщо ми хочемо взяти цілий вхід? Нормальні цілі типи є двійковими мовами, такими як C. Або ви маєте на увазі, що введення / вихід не може бути масивом або рядком цілих чи ASCII нулів / одиниць?
Пітер Кордес

Відповіді:


22

Haskell , 25 байт

pred.until(<2)(/2).(+0.5)

Спробуйте в Інтернеті!

Вихідні знаки після коми, одноіндексовані без початкового нульового члена.

Додає 0,5 до введення, потім наполовину, поки результати не стануть нижче 2, а потім віднімає 1. Використання виразного виразу зберігає 1 байт на

f n=until(<2)(/2)(n+0.5)-1

11

Java 10, 68 64 байт

Спочатку спробуйте в коді гольф!

Варіант 1: знайти n -й елемент (1-індексований)

-4 байти завдяки @Kevin Cruijssen

n->{int x=0;for(;n>>++x!=1;);return((~(1<<x)&n)*2.+1)/(1<<x+1);}

Це анонімний метод, який знаходить n -й член шляхом видалення найбільш значущого біта з n , подвоюючи його і додаючи його, а потім ділить на наступну найвищу потужність 2.

Спробуйте в Інтернеті!

Посібник із коду:

n->{                      // builds anonymous function with input n
int x=0;                  // stores floor of log(n) (base 2) for most significant digit
for(;n>>++x!=1;);         // calculates floor of log(n) by counting right shifts until 1
return((~(1<<x)&n)        // removes most significant digit of n
*2.+1)                     // multiplies 2 and adds 1 to get the odd numerator
/(1<<x+1);}               // divides by the next highest power of 2 and returns`

Відредагує, якщо потрібно надрукувати остаточне значення, а не повертати його.


Ласкаво просимо до PPCG, приємно, що ти з нами :)
Shaggy

Привіт, Ласкаво просимо до PPCG! Чудова перша відповідь, +1 від мене. Наразі це такий самий підрахунок байтів, як і моя відповідь на Java, але ви можете все-таки пограти в деякі частини вашої відповіді, щоб зробити її коротшою, ніж моя: Натомість {}цикл може бути ;замість цього; ви можете видалити пробіл після return; 2.0може бути 2.; І змінюючи n>>x!=1;x++, 1<<xі 1<<x+1до n>>x++!=1;, 1<<x-1, 1<<xвідповідно , також зберігає байт. Спробуйте в Інтернеті: 64 байти . Насолодитися перебуванням!
Kevin Cruijssen

Ну, і якщо ви ще цього не бачили: Поради щодо гольфу на Яві та Поради щодо гольфу на <всіх мовах> цікаві для прочитання. :)
Кевін Круїссен

Дивіться мою відповідь на 30 байтів , спочатку заснований на вашому, але гольф і гольф і гольф.
Олів'є Грегоар

9

MathGolf , 5 4 байти

╫\╨]

Спробуйте в Інтернеті!

Як це виглядатиме, коли оператор працює правильно

╫\)╨]   (")" adds 1 to TOS, making rounding behave as expected)

Спробуйте в Інтернеті!

Пояснення

╫     Left-rotate all bits in input
 \    Swap top two elements on stack, pushing the input to the top
  ╨   Round up to nearest power of 2
   ]  Wrap in array (just for pretty printing)

Я взяв своє натхнення з цього питання, щоб вирішити проблему, моє "власне" рішення було приблизно 10-12 байтів, я думаю.

Я мав намір для раунду до найближчої сили 2 повернути саме число, якщо воно було числом два, але через помилку він обертається до наступної потужності двох (наприклад, 4 -> 8 замість 4 -> 4 ). Це доведеться виправити пізніше, але тепер це заощаджує мені один байт.


2
Я не знаю MathGolf, але якщо це ]не відповідає іншій формі, ніж форматування виводу, я б сказав, що вам не потрібно включати його у свій байт.
Кудлатий

2
Я був не впевнений у цьому. Оскільки стек друкується на виході як об'єднаний рядок, він виводить стек з цифрами 1 і 2 як 12. Якщо це все-таки рахується, я
видаляю

Я думаю, ви повинні залишити його. Іноді економиться байт, щоб вивести стек як один рядок, іноді це обійдеться вам у байт.
H.PWiz

@ H.PWiz, це було моїм оригінальним мисленням, оскільки, здається, справедливо використовувати сильні сторони вашої мови. Деякі мови друкують верхню частину стеку лише після завершення, деякі друкують її як список. Зазвичай це різниця в 1 байт, але це частина проблеми.
maxb

8

Java 10, 89 85 70 69 68 байт

v->{for(float j,t=2;;t*=2)for(j=1;j<t;j+=2)System.out.println(j/t);}

Порт відповіді 05AB1E @Emigma , тому виводиться також десяткові числа також на невизначений термін.
-15 байт завдяки @Arnauld .

Спробуйте в Інтернеті.

Пояснення:

v->{                      // Method with empty unused parameter and no return-type
  for(float j,t=2;;       //  Loop `t` from 2 upwards indefinitely,
                   t*=2)  //  doubling `t` after every iteration
    for(j=1;j<t;          //   Inner loop `j` in the range [1, `t`),
                j+=2)     //   in steps of 2 (so only the odd numbers)
      System.out.println( //    Print with trailing new-line:
        j/t);}            //     `j` divided by `t`

1
Як часто я можу сказати, що я половину вашої кількості байтів? Ну, я думаю, що це вперше ;-)
Олів'є Грегоар

@ OlivierGrégoire Dang, тепер це вражаюча відповідь на Java. :) Я бачив вашу 37-байтну версію як коментар до відповіді TCFP, але ви навіть позбавили більше байтів. Це виглядає настільки надзвичайно просто у вашій 30-байтній версії, але все ще геніально, як ви переграли його від початкової версії. Молодці!
Kevin Cruijssen



7

Java (JDK 10) , 30 байт

n->(n+.5)/n.highestOneBit(n)-1

Спробуйте в Інтернеті!

Повертає п й елемент у послідовності.

Ця відповідь спочатку була послідовністю гольфу відповіді Java на TCFP . Зрештою, гольфи вже не схожі на оригінальну відповідь (хоча використовувана математика однакова), тому я вирішив розмістити гольфів як окрему відповідь, а не просто коментувати відповідь TCFP. Тож якщо вам подобається ця відповідь, також підкажіть відповідь TCFP ! ;-)

Проміжними гольфами були:

n->{int x=0;for(;n>>++x!=1;);return((~(1<<x)&n)*2.+1)/(1<<x+1);} // 64 bytes (TCFP's answer when I started golfing)
n->{int x=0;for(;n>>++x!=1;);x=1<<x;return((~x&n)*2.+1)/x/2;}    // 61 bytes
n->{int x=n.highestOneBit(n);return((~x&n)*2.+1)/x/2;}           // 54 bytes
n->{int x=n.highestOneBit(n);return((~x&n)+.5)/x;}               // 50 bytes
n->((n&~(n=n.highestOneBit(n)))+.5)/n                            // 37 bytes
n->(n-(n=n.highestOneBit(n))+.5)/n                               // 34 bytes
n->(n+.5)/n.highestOneBit(n)-1                                   // 30 bytes, current score

І я сидів тут, думаючи, що моя відповідь така коротка, як я міг би це зробити, ви підійдіть і скоротіть її більш ніж наполовину! Дивовижні речі, безумовно, заслуговує +1 від мене.
TCFP

@TCFP Це був ітераційний процес протягом декількох годин. Я фактично розмістив кожен проміжний гольф як коментар до вашої відповіді, але видалив їх, коли я знайшов кращих гольфів. Дякую за похвалу ;-)
Олів'є Грегоар

6

05AB1E , 11 8 байт

Збережено 3 байти завдяки Kevin Cruijssen .

∞oDÅÉs/˜

Спробуйте в Інтернеті!

Пояснення

∞         # start an infinite list [1...
 o        # calculate 2**N
  D       # duplicate
   ÅÉ     # get a list of odd numbers up to 2**N
     s/   # divide each by 2**N
       ˜  # flatten

1
-1 байт, використовуючи (нескінченний список, починаючи з 1):∞oεDÅÉs/}˜
Кевін Круїйсен

@KevinCruijssen: Класно! Це команда, яку я раніше не бачив. Дякую :)
Emigna

1
Ах, і приємний спосіб збереження ще двох байтів через неявне відображення .. Навіть не думав про це,
хаха

1
: O як це можливо. Ви звели питання ~ 2 сторінки на 8 байт.
Cullub

Я думав, використовуючи прості числа та перелік [1,2,4,4,8,8,8,8,16,16,...,2**n]та передчуваючи правильний індексований прем'єр, за яким слідує /... Але це було не так добре. Ну, але не 8-bytesдобре. Щось подібне 9LoDÅP)ζ.
Чарівна восьминога урна


5

PowerShell , 40 байт

for($i=2;;$i*=2){1..$i|?{$_%2}|%{$_/$i}}

Спробуйте в Інтернеті!

Виводить нескінченну послідовність у вигляді десяткових значень. Враховуючи мовні обмеження, з часом виникнуть проблеми з точністю, але легко обробляються перші 1000 записів.

Починається з налаштування $i=2, після чого входить у forцикл. Кожною ітерацією ми побудуємо діапазон із 1..$iта витягнемо непарні значення |?{$_%2}. Вони подаються у власну внутрішню петлю, де ми ділимо кожну, щоб отримати десятковий |%{$_/$i}. Вони залишаються на трубопроводі і виводяться, коли трубопровід промивається після кожної forітерації. Кожну ітерацію ми просто збільшуємо $i, $i*=2щоб отримати наступний раунд.



5

Haskell, 40 bytes

s=(1,2):[(i*2+u,j*2)|(i,j)<-s,u<-[-1,1]]

Try it online!

Infinite sequence as pairs of integers (starting from (1,2)).

Quite a bit longer than @nimi's answer, but the approach is completely different, so I decided to post it anyway.

This solution is based on the following observation.

Consider the infinite sequence

{12,14,34,18,38,58,78,116,316,}
and apply the following steps.

  • Replace every number ij in the sequence with the list {2i12j,2i+12j}:
    {{14,34},{18,38},{58,78},{116,316},}
  • Join all the lists into a single sequence:
    {14,34,18,38,58,78,116,316,}
  • Add 12 at the beginning of the sequence:
    {12,14,34,18,38,58,78,116,316,}

Notice how you get back to the sequence you started with!

The solution exploits this fact (together with Haskell's laziness) to compute the sequence s.


4

Python 2 - 68 66 bytes

-2 bytes thanks to Kevin

from math import*
def g(n):a=2**floor(log(n,2));print(n-a)*2+1,2*a

Try it Online!


You can golf 1 byte by changing return 2*(n-a) to return(n-a)*2. And you could save an additional byte by using Python 2 instead of 3, so return can be print (with parenthesis).
Kevin Cruijssen

2
@KevinCruijssen For someone who doesn't use Python, you certainly are a better Python programmer than me.
Don Thousand

Hehe. :D Simple things like this comes with experience I guess. I'm on this site for about two years now I think (EDIT: Since April 2016). I sometimes even suggests things to golf for answers that are written in languages I had never seen before.. Some basic things work in most languages. For example, last week I suggested a golf for a T-SQL answer, and I once suggested a golf in a Red answer. xD
Kevin Cruijssen

2
44 bytes using len and bin instead of log.
ovs



4

R, 42 bytes

function(n)c(y<-2^(log2(n)%/%1)*2,2*n-y+1)

Try it online!

Returns a pair Denominator,Numerator. Uses the formula N=2(n2log2(n))+1 from the Josephus sequence and D=2log2(n)+1 from the other sequence. Happily we are able to re-use the denominator as the two formulas have quite a lot in common!



3

MATL, 8 bytes

BnWGEy-Q

Try it online!

Returns Numerator, then Denominator. Uses the same method as my R answer, although it's a bit more efficient.

Explanation, with input 5:

           # implicit input 5
B          # convert to array of bits
           # STACK: [[1 0 1]]
n          # length (place of Most Significant Bit)
           # STACK: [3]
W          # elementwise raise 2^x
           # STACK: [8]
G          # paste input
           # STACK: [8, 5]
E          # double
           # STACK: [8, 10]
y          # copy from below
           # STACK: [8, 10, 8]
-          # subtract
           # STACK: [8, 2]
Q          # increment
           # STACK: [8, 3]
           # implicit end of program, display stack contents

2

Shakespeare Programming Language, 426 bytes

,.Ajax,.Ford,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:You be the sum ofyou a cat.Ford:You cat.Scene V:.Ford:Is twice you nicer I?If solet usScene X.You be twice you.Let usScene V.Scene X:.Ford:Remember twice you.You be the sum oftwice the remainder of the quotient betweenI you a cat.Open heart.You big big big big big cat.Speak thy.Recall.Open heart.You be twice the sum ofa cat a big big cat.Speak thy.Let usAct I.

Try it online!

Outputs the sequence infinitely as both numbers separated by a space, with each item being separated by a newline.


Love it. Lol You be twice the sum of a cat
Cullub

Actually, it's "twice the sum ofa cat a big big cat" (i.e. 10 for some reason).
JosiahRyanW


2

Excel 48 28 Bytes

Saved 20 bytes (!) thanks to tsh

=(A1+0.5)/2^INT(LOG(A1,2))-1

=MOD(A1+0.5,2^(INT(LOG(A1,2))))/2^INT(LOG(A1,2))

Assumes value in A1, output is in decimal. If you want the output to be in fraction, you can create a custom format for the output cell as "0/###0" and it will show it as fraction.

Explanation: Difficult to explain, since there is a shortcut taken to get to this formula. Basically the numerator is a bit shift left of the input, and the denominator is the next power of 2 higher than the number input.

I originally started with Excel built in functions for BITLSHIFT and BITRSHIFT, but they will shift the entire 48 bits which is not what you want. The functions DEC2BIN (and BIN2DEC) have a limit of -512 to 511 (10 bits) so this wouldn't work. Instead I had to rebuild the number with a modulus of the original number, then times two, then add 1 (since the left digit would always be 1 before a shift).

=MOD(A1                        Use MOD for finding what the right digits are
       +0.5                    this will later add the left "1" to the right digits
           ,2^INT(LOG(A1,2)))) Take Log base 2 number of digits on the right
                               this creates the numerator divided by 2 (explained later)
/ 2^INT(LOG(A1,2))             The denominator should be 2^ (Log2 + 1) but instead of 
                               adding a 1 here, we cause the numerator to be divided by 2 instead
                               This gives us a fraction.  In the numerator, we also added .5
                               instead of 1 so that we wouldn't need to divide it in both the
                               numerator and denominator
Then tsh showed how I could take the int/log out of the mod and remove it from numerator/denominator. 

Examples: enter image description here


What about =(A1+0.5)/2^INT(LOG(A1,2))-1?
tsh

2

C++, 97 75 71 bytes

-26 bytes thanks to tsh, ceilingcat, Zacharý

float f(int i){float d=2,n=1;while(--i)n=d-n==1?d*=2,1:n+2;return n/d;}

Testing code :

std::cout << "1\t:\t" << f(1) << '\n';
std::cout << "2\t:\t" << f(2) << '\n';
std::cout << "3\t:\t" << f(3) << '\n';
std::cout << "4\t:\t" << f(4) << '\n';
std::cout << "10\t:\t" << f(10) << '\n';
std::cout << "100\t:\t" << f(100) << '\n';
std::cout << "511\t:\t" << f(511) << '\n';
std::cout << "512\t:\t" << f(512) << '\n';

You may just omit if(!i)return 0; since 0 is not required in the challenge.
tsh

1
When trying to golf C-like language. You should avoid using while but try for. for(;exp;) is as same as while(exp) but you can write two more other statement into it. Prefer ?: instead of if else, which would be shorter in most cases.
tsh

1
I don't think you need the (...) around d-n-1.
Zacharý






1

><>, 19 18 bytes

Using xnor's idea, fixed by Jo King, -1 byte by making better use of the mirrors and another -2 bytes by Jo King because the ! was superfluous and ; is not required.

2*1+\1-n
2:,2/?(

Try it online!


You should be checking if it is smaller than 2 first, otherwise the first element is -0.25. Fix for the same amount of bytes
Jo King

Thanks! I also managed to remove another byte by reusing the mirrors.
PidgeyUsedGust

Why did you invert the condition? 16 bytes
Jo King

Didn't notice that it would continue the loop. Are we allowed to not properly finish?
PidgeyUsedGust

Yeah, terminating with an error is fine as long as the OP doesn't specify otherwise
Jo King


1

APL (Dyalog Unicode), 15 bytes

1-⍨.5∘+÷2*∘⌊2⍟⊢

Try it online!

Anonymous prefix lambda.

Thanks to Adám for 4 bytes and to Cows quack for 2 bytes.

How:

1-⍨.5∘+÷2*∘⌊2⍟⊢  Anonymous lambda, argument   10
            2⍟⊢  Log (⍟) of  in base 2. 210  3.32192809489...
                 Floor. 3.32192809489...  3
        2*∘       Take that power of 2. 2³  8
       ÷          Use that as denominator
   .5∘+            + 0.5  10.5. Using that as numerator: 10.5÷8  1.3125
1-⍨               Swap the arguments (⍨), then subtract. 1-⍨1.3125  1.3125-1  0.3125

1

C# (.NET Core), 69 bytes

a=>{int b=1,c=2;while(a-->1){b+=2;if(b>c){b=1;c*=2;}}return b+"/"+c;}

Try it online!

Ungolfed:

a=> {
    int b = 1, c = 2;   // initialize numerator (b) and denominator (c)
    while (a-- > 1)     // while a decrements to 1
    {
        b += 2;         // add 2 to b
        if (b > c)      // if b is greater than c:
        {
            b = 1;      // reset numerator to 1
            c *= 2;     // double denominator
        }
    }
    return b + "/" + c; // return fraction as string
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.