I want my book to be away from this table

21

2

Story

So I have a book that I want to separate from my table with nothing but other books. I want to know how many books do I need to achieve this with \$n\$ book lengths.

Here's a visualization that my friend at Wolfram drew for me:

a visualization from Wolfram

More information about the topic in Wolfram and Wikipedia.

Challenge

Given an integer input \$n\$, output how many books needed for the top book to be \$n\$ book length away from the table horizontally.
or
Find the smallest integer value of \$m\$ for input \$n\$ in the following inequality. $$\sum_{i=1}^{m}\frac{1}{2i} \geq n$$

Edit: for fractions use at least a IEEE single-precision floating point. sorry for editing challenge after posting

(OEIS A014537)

Test cases

 1          4
 2         31
 3        227
 5      12367
10  272400600

betseg

Posted 2018-01-27T12:35:14.337

Reputation: 8 493

1https://www.youtube.com/watch?v=pBYPXsGka74 <-- related – streetster – 2018-01-27T16:24:43.740

Does it have to be using this particular arrangement of books, which IIRC is not optimal? – user253751 – 2018-02-05T03:46:04.283

Answers

13

Octave, 41 40 33 bytes

1 byte saved thanks to @Dennis

@(n)find(cumsum(.5./(1:9^n))>n,1)

Try it online!

Explanation

This uses the fact that harmonic numbers can be lower-bounded by a logarithmic function.

Also, the >= comparison can be replaced by > because harmonic numbers cannot be even integers (thanks, @Dennis!).

@(n)                                   % Anonymous function of n
                     1:9^n             % Range [1 2 ... 9^n]
                .5./(     )            % Divide .5 by each entry
         cumsum(           )           % Cumulative sum
                            >n         % Is each entry greater than n?
    find(                     ,1)      % Index of first true entry

Luis Mendo

Posted 2018-01-27T12:35:14.337

Reputation: 87 464

11

Python 3, 35 bytes

f=lambda n,k=2:n>0and-~f(n-1/k,k+2)

Try it online!

Dennis

Posted 2018-01-27T12:35:14.337

Reputation: 196 637

10

Husk, 8 bytes

V≥⁰∫m\İ0

Try it online!

Since Husk uses rational numbers when it can, this has no floating point issues

Explanation

      İ0    The infinite list of positive even numbers
    m\      Reciprocate each
   ∫        Get the cumulative sum
V           Find the index of the first element
 ≥⁰         that is greater than or equal to the input

H.PWiz

Posted 2018-01-27T12:35:14.337

Reputation: 10 962

8 bytes, but in which charset? – john16384 – 2018-01-27T23:03:52.197

3

@john16384 Husk has it's own codepage where each symbol corresponds to a single byte. Here is the corresponding hexdump

– H.PWiz – 2018-01-27T23:15:57.477

5

JavaScript, 30 bytes

A recursive function so it'll crap out pretty early.

f=(n,x=0)=>n>0?f(n-.5/++x,x):x

Try it online

Shaggy

Posted 2018-01-27T12:35:14.337

Reputation: 24 623

4

Haskell, 38 bytes

k!n|n<=0=0|x<-n-1/(2*k)=1+(k+1)!x
(1!)

BlackCap

Posted 2018-01-27T12:35:14.337

Reputation: 3 576

3

Javascript (ES6), 34 bytes

n=>eval("for(i=0;n>0;n-=.5/i)++i")

Ungolfed

n => {
    for(i = 0; n > 0; ++i)
        n -= .5 / i
    return i;
}

Test Cases

f=n=>eval("for(i=0;n>0;n-=.5/i)++i")
<button onclick="console.log(f(1))">Run for n = 1</button>
<button onclick="console.log(f(2))">Run for n = 2</button>
<button onclick="console.log(f(3))">Run for n = 3</button>
<button onclick="console.log(f(5))">Run for n = 5</button>
<button onclick="console.log(f(10))">Run for n = 10</button>

Herman L

Posted 2018-01-27T12:35:14.337

Reputation: 3 611

Came up with a similar solution using recursion for 30 bytes. Dunno whether to post it or not, after seeing yours. – Shaggy – 2018-01-27T14:14:48.340

1I may be missing something, but why do you need to wrap it in an eval statement? – caird coinheringaahing – 2018-01-27T22:03:56.057

1@cairdcoinherigaahing, without the eval the i variable would need to be returned at the end, at the cost of a few more bytes. – Shaggy – 2018-01-27T22:12:23.490

3

Swift, 65 bytes

func f(n:Double){var i=0.0,s=i;while s<n{i+=1;s+=0.5/i};print(i)}

Try it online!

Ungolfed

func f(n:Double) {
  var i = 0.0, s = 0.0
  while s < n {
    i += 1;
    s += 0.5 / i
  }
  print(i)
}

Herman L

Posted 2018-01-27T12:35:14.337

Reputation: 3 611

3

R, 39 bytes

function(n){while((F=F+.5/T)<n)T=T+1;T}

Try it online!

Brute Force!

Giuseppe

Posted 2018-01-27T12:35:14.337

Reputation: 21 077

2

Jelly, 8 bytes

RİSH:ð1#

This is very slow.

Try it online!

Dennis

Posted 2018-01-27T12:35:14.337

Reputation: 196 637

2

Haskell, 71 49 48 bytes

f x=length.fst.span(<x).scanl(+)0$(0.5/)<$>[1..]

@BMO saved me a whopping 22 bytes!

BlackCap

Posted 2018-01-27T12:35:14.337

Reputation: 3 576

2

Julia 0.6, 30 27 bytes

<(n,i=1)=n>0?n-.5/i<i+1:i-1

Try it online!

Only works up to n = 6, because Julia has no tail call optimization.

-3 bytes thanks to Dennis.

LukeS

Posted 2018-01-27T12:35:14.337

Reputation: 421

2

TI-BASIC, 27 bytes

Prompts user for input and displays output on termination. Note: ⁻¹ is the -1 (inverse) token.

Input N
1
Repeat 2N≤Σ(I⁻¹,I,1,Ans
Ans+1
End
Ans

kamoroso94

Posted 2018-01-27T12:35:14.337

Reputation: 739

2

If you're going to save Ans in N immediately, then Input N or Prompt N is an input method that saves you one byte over Ans→N. And M can be replaced by Ans, so that 1→M becomes 1 and M+1→M becomes Ans+1. (But I am skeptical about an output in Ans that does not get displayed - see this - so maybe ending with :Ans is appropriate: then the value will be shown in place of "Done".)

– Misha Lavrov – 2018-01-31T04:32:47.967

Thank you! I knew Ans→N felt funny. Nice optimizations. Also took your advice on output just to be safe. Still comes out with a net -3 bytes :D – kamoroso94 – 2018-01-31T05:22:36.117

1

Japt, 12 bytes

The same length as, but slightly more efficient than, the recursive option.

@T¨(Uµ½÷X}a1

Try it


Explanation

@T¨(Uµ½÷X}a1
                 :Implicit input of integer U
@        }a1     :Return the first number X >=1 that returns truthy when passed through the following function
 T               :Zero
  ¨              :Greater than or equal to
    Uµ           :Decrement U by...
      ½÷X        :0.5 divided by X

Shaggy

Posted 2018-01-27T12:35:14.337

Reputation: 24 623

1

05AB1E, 11 bytes

XµN·zODI›}N

Try it online!

Explanation

Xµ       }    # loop until counter is 1
  N·z         # push 1/(2*N)
     O        # sum the stack
      DI›     # break if the sum is greater than the input
          N   # push N

Emigna

Posted 2018-01-27T12:35:14.337

Reputation: 50 798

1

Pyth, 10 bytes

f!>Qsmc1yh

Try it online!

Extremely slow.

Pyth, 10 bytes

fgscL1STyQ

Try it online!

Mr. Xcoder

Posted 2018-01-27T12:35:14.337

Reputation: 39 774

1

J, 22 bytes

-6 bytes thanks to frownyfrog

I.~0+/\@,1%2*1+[:i.9&^

Try it online!

original answer

Luis's answer in J:

1+]i.~[:<.[:+/\1%2*1+[:i.9&^

Ungolfed

1 + ] i.~ [: <. [: +/\ 1 % 2 * 1 + [: i. 9&^

Mostly curious to see if it can be drastically improved (cough paging miles)

Explanation

1 +      NB. 1 plus... 
] i.~    NB. find the index of the arg in...
[: <.    NB. the floor of...
[: +/\   NB. the sumscan of...
1 %      NB. the reciprical of...
2 *      NB. two times...
1 +      NB. 1 plus...
[: i.    NB.  the integers up to 
9&^      NB. 9 raised to the power of the arg

Try it online!

Jonah

Posted 2018-01-27T12:35:14.337

Reputation: 8 729

1+]i.~[:<. -> 1+]I.~ -> I.~0, – FrownyFrog – 2018-01-29T05:06:39.400

ofc! thank you frownyfrog – Jonah – 2018-01-29T05:15:43.187

And then I.~0+/\@, – FrownyFrog – 2018-01-29T07:43:55.907

If you edit, you’ll beat Julia :) – FrownyFrog – 2018-01-31T20:29:33.833

@FrownyFrog, done. if you have some time, i would love to see you solve this one: https://codegolf.stackexchange.com/questions/154345/bracket-expansion. all the solutions i can think of are too verbose to post in good conscience...

– Jonah – 2018-01-31T22:09:32.967

0

PHP, 35 bytes

while($argv[1]>$s+=.5/++$i);echo$i;

Run it using the CLI:

$ php -d error_reporting=0 -r 'while($argv[1]>$s+=.5/++$i);echo$i;' 5

axiac

Posted 2018-01-27T12:35:14.337

Reputation: 749

0

Wolfram Language (Mathematica), 40 bytes

⌈x/.NSolve[HarmonicNumber@x==2#,x]⌉&

Try it online!

alephalpha

Posted 2018-01-27T12:35:14.337

Reputation: 23 988

0

Java 8, 49 bytes

n->{float r=0,s=0;for(;s<n;)s+=.5f/++r;return r;}

Explanation:

Try it online. (Times out for test cases above n=7.)

n->{             // Method with integer parameter and float return-type
  float r=0,     //  Result-float, starting at 0
        s=0;     //  Sum-float, starting at 0
  for(;s<n;)     //  Loop as long as the sum is smaller than the input
    s+=.5f/++r;  //   Increase the sum by `0.5/(r+1)`,
                 //   by first increasing `r` by 1 with `r++`
  return r;}     //  Return the result-float

Kevin Cruijssen

Posted 2018-01-27T12:35:14.337

Reputation: 67 575

0

tinylisp, 98 bytes

(load library
(d _(q((k # N D)(i(l N(* D # 2))(_(inc k)#(+(* N k)D)(* D k))(dec k
(q((#)(_ 1 # 0 1

The last line is an unnamed lambda function that takes the number of book-lengths and returns the number of books needed. Try it online!

Explanation

The only numeric data type tinylisp has is integers, so we calculate the harmonic series as a fraction by keeping track of the numerator and denominator. At each step, N is the numerator, D is the denominator, and k is the sum index. We want the new partial sum to be N/D + 1/k, or (N*k + D)/(D*k). Thus, we recurse with a new numerator of N*K + D, a new denominator of D*k, and a new index of k+1.

The recursion should halt once the partial sum is greater than or equal to #, the desired number of book-lengths. At this point, we've gone one book too far, so we return k-1. The condition is 1/2 * N/D < #; multiplying out the denominator, we get N < D*#*2, which is the golfiest way to write it.

The recursive helper function _ does all these calculations; the main function is merely a one-argument wrapper that calls _ with the correct starting values for k, N, and D.

DLosc

Posted 2018-01-27T12:35:14.337

Reputation: 21 213