Quickest way of finding the largest integer n such that n! has length of m bits

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite
1













Factstone Benchmark



Amtel has announced that it will release a 128-bit computer chip by
2010, a 256-bit computer by 2020, and so on, continuing its strategy
of doubling the word-size every ten years. (Amtel released a 64-bit
computer in 2000, a 32-bit computer in 1990, a 16-bit computer in
1980, an 8-bit computer in 1970, and a 4-bit computer, its first, in
1960.)



Amtel will use a new benchmark – the Factstone – to advertise the
vastly improved capacity of its new chips. The Factstone rating is
defined to be the largest integer $n$ such that $n!$ can be represented as an unsigned integer in a computer word.



Given a year $1960le yle 2160$, what will be the Factstone rating of Amtel's most recently released
chip?



Input



There are several test cases. For each test case, there is one line of
input containing $y$. A line containing $0$ follows the last test case. >



Output



For each test case, output a line giving the Factstone rating.



Sample Input 1



1960
1981
0


Sample Output 1



3
8



import math
n = int(input())
while n != 0:
n = (n - 1960) / 10 + 2
m = pow(2,n)
i = 1
while m > 0:
m -= math.log(i,2)
i += 1
print(i - 2)
n = int(input())


Can someone please help me time optimize this code? I'm doing it for a site that checks my code but I always fail at the time check.







share|improve this question





















  • You'd get better results by doing a binary search for the answer rather than by searching linearly. Use memoization or some lookup tables to avoid recalculating things that were already calculated.
    – Snowbody
    Jan 16 at 15:00
















up vote
3
down vote

favorite
1













Factstone Benchmark



Amtel has announced that it will release a 128-bit computer chip by
2010, a 256-bit computer by 2020, and so on, continuing its strategy
of doubling the word-size every ten years. (Amtel released a 64-bit
computer in 2000, a 32-bit computer in 1990, a 16-bit computer in
1980, an 8-bit computer in 1970, and a 4-bit computer, its first, in
1960.)



Amtel will use a new benchmark – the Factstone – to advertise the
vastly improved capacity of its new chips. The Factstone rating is
defined to be the largest integer $n$ such that $n!$ can be represented as an unsigned integer in a computer word.



Given a year $1960le yle 2160$, what will be the Factstone rating of Amtel's most recently released
chip?



Input



There are several test cases. For each test case, there is one line of
input containing $y$. A line containing $0$ follows the last test case. >



Output



For each test case, output a line giving the Factstone rating.



Sample Input 1



1960
1981
0


Sample Output 1



3
8



import math
n = int(input())
while n != 0:
n = (n - 1960) / 10 + 2
m = pow(2,n)
i = 1
while m > 0:
m -= math.log(i,2)
i += 1
print(i - 2)
n = int(input())


Can someone please help me time optimize this code? I'm doing it for a site that checks my code but I always fail at the time check.







share|improve this question





















  • You'd get better results by doing a binary search for the answer rather than by searching linearly. Use memoization or some lookup tables to avoid recalculating things that were already calculated.
    – Snowbody
    Jan 16 at 15:00












up vote
3
down vote

favorite
1









up vote
3
down vote

favorite
1






1






Factstone Benchmark



Amtel has announced that it will release a 128-bit computer chip by
2010, a 256-bit computer by 2020, and so on, continuing its strategy
of doubling the word-size every ten years. (Amtel released a 64-bit
computer in 2000, a 32-bit computer in 1990, a 16-bit computer in
1980, an 8-bit computer in 1970, and a 4-bit computer, its first, in
1960.)



Amtel will use a new benchmark – the Factstone – to advertise the
vastly improved capacity of its new chips. The Factstone rating is
defined to be the largest integer $n$ such that $n!$ can be represented as an unsigned integer in a computer word.



Given a year $1960le yle 2160$, what will be the Factstone rating of Amtel's most recently released
chip?



Input



There are several test cases. For each test case, there is one line of
input containing $y$. A line containing $0$ follows the last test case. >



Output



For each test case, output a line giving the Factstone rating.



Sample Input 1



1960
1981
0


Sample Output 1



3
8



import math
n = int(input())
while n != 0:
n = (n - 1960) / 10 + 2
m = pow(2,n)
i = 1
while m > 0:
m -= math.log(i,2)
i += 1
print(i - 2)
n = int(input())


Can someone please help me time optimize this code? I'm doing it for a site that checks my code but I always fail at the time check.







share|improve this question














Factstone Benchmark



Amtel has announced that it will release a 128-bit computer chip by
2010, a 256-bit computer by 2020, and so on, continuing its strategy
of doubling the word-size every ten years. (Amtel released a 64-bit
computer in 2000, a 32-bit computer in 1990, a 16-bit computer in
1980, an 8-bit computer in 1970, and a 4-bit computer, its first, in
1960.)



Amtel will use a new benchmark – the Factstone – to advertise the
vastly improved capacity of its new chips. The Factstone rating is
defined to be the largest integer $n$ such that $n!$ can be represented as an unsigned integer in a computer word.



Given a year $1960le yle 2160$, what will be the Factstone rating of Amtel's most recently released
chip?



Input



There are several test cases. For each test case, there is one line of
input containing $y$. A line containing $0$ follows the last test case. >



Output



For each test case, output a line giving the Factstone rating.



Sample Input 1



1960
1981
0


Sample Output 1



3
8



import math
n = int(input())
while n != 0:
n = (n - 1960) / 10 + 2
m = pow(2,n)
i = 1
while m > 0:
m -= math.log(i,2)
i += 1
print(i - 2)
n = int(input())


Can someone please help me time optimize this code? I'm doing it for a site that checks my code but I always fail at the time check.









share|improve this question












share|improve this question




share|improve this question








edited Jan 16 at 14:38









Graipher

20.5k43081




20.5k43081









asked Jan 16 at 11:47









gal zakrajsek

492




492











  • You'd get better results by doing a binary search for the answer rather than by searching linearly. Use memoization or some lookup tables to avoid recalculating things that were already calculated.
    – Snowbody
    Jan 16 at 15:00
















  • You'd get better results by doing a binary search for the answer rather than by searching linearly. Use memoization or some lookup tables to avoid recalculating things that were already calculated.
    – Snowbody
    Jan 16 at 15:00















You'd get better results by doing a binary search for the answer rather than by searching linearly. Use memoization or some lookup tables to avoid recalculating things that were already calculated.
– Snowbody
Jan 16 at 15:00




You'd get better results by doing a binary search for the answer rather than by searching linearly. Use memoization or some lookup tables to avoid recalculating things that were already calculated.
– Snowbody
Jan 16 at 15:00










2 Answers
2






active

oldest

votes

















up vote
6
down vote














import math
n = int(input())
while n != 0:
n = (n - 1960) / 10 + 2



What does n represent now? n as a name for the value which is called y in the task description is already unnecessarily obscure, but aliasing it really confuses things.



In addition, note that in Python / does floating point division. If the output for 1969 should be the same as the output for 1960 (and I'm pretty sure the spec requires that) then there's a bug here.




 m = pow(2,n)



What does m represent? If you want people to review your code, use descriptive names!




 while m > 0:
m -= math.log(i,2)
i += 1



How many times does this loop execute for the largest possible input? How can you avoid a linear loop? (Hint: a certain Stirling analysed $log n!$ ...)



(Or, arguably cheating, there are only 21 decades in view, so you could hard-code a lookup.)






share|improve this answer






























    up vote
    2
    down vote













    You need to use some maths.



    You want to know whether



    $n! < 2^b$ (where $b$ is the number of bits)



    This is equivalent of:



    $log n! lt log 2^b$

    $log n! lt blog 2$



    Then we need efficient $log n!$ calculation..



    $log n!$ = $log (n(n-1)!)$ = $log n + log (n-1)!$



    We can pre-compute the log n! for the first some n



    The maximum year = 2160, with equals a 4194304 bits computer.



    As I'm trying I see you need way to much pre-computed log n!, so we need a better way of calculating log n!. There exists an solution when log is chosen to be the natural logarithm ln:
    http://mathworld.wolfram.com/StirlingsApproximation.html



    It states:



    $ ln n! ≈ n ln n-n+1$ (for big n)



    so we need to solve:



    $ n ln n-n+1 < b ln 2$



    For small n we can still use a lookup table. You can determine where the error gets small enough to stop using the lookup-table.






    share|improve this answer























    • If $log$ is $log_2$, then you can use $log_2n! lt b$. Which is really fast and simple.
      – Peilonrayz
      Jan 16 at 15:13










    • Yes, but n! get really bit really fast, so need to find something smarter there yet. Probably log ab = log a + log b ;)
      – RobAu
      Jan 16 at 15:16






    • 1




      Do you realise that what you've done here is propose that OP make no changes to his code?
      – Peter Taylor
      Jan 16 at 15:23






    • 2




      I believe it is not, as I will never calculate the powers of 2 and get into the big numbers?
      – RobAu
      Jan 16 at 15:26










    • Nor does OP's code. (I agree that m = pow(2,n) looks like it's doing that, but it turns out to be calculating $b$).
      – Peter Taylor
      Jan 16 at 15:56










    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185210%2fquickest-way-of-finding-the-largest-integer-n-such-that-n-has-length-of-m-bits%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    6
    down vote














    import math
    n = int(input())
    while n != 0:
    n = (n - 1960) / 10 + 2



    What does n represent now? n as a name for the value which is called y in the task description is already unnecessarily obscure, but aliasing it really confuses things.



    In addition, note that in Python / does floating point division. If the output for 1969 should be the same as the output for 1960 (and I'm pretty sure the spec requires that) then there's a bug here.




     m = pow(2,n)



    What does m represent? If you want people to review your code, use descriptive names!




     while m > 0:
    m -= math.log(i,2)
    i += 1



    How many times does this loop execute for the largest possible input? How can you avoid a linear loop? (Hint: a certain Stirling analysed $log n!$ ...)



    (Or, arguably cheating, there are only 21 decades in view, so you could hard-code a lookup.)






    share|improve this answer



























      up vote
      6
      down vote














      import math
      n = int(input())
      while n != 0:
      n = (n - 1960) / 10 + 2



      What does n represent now? n as a name for the value which is called y in the task description is already unnecessarily obscure, but aliasing it really confuses things.



      In addition, note that in Python / does floating point division. If the output for 1969 should be the same as the output for 1960 (and I'm pretty sure the spec requires that) then there's a bug here.




       m = pow(2,n)



      What does m represent? If you want people to review your code, use descriptive names!




       while m > 0:
      m -= math.log(i,2)
      i += 1



      How many times does this loop execute for the largest possible input? How can you avoid a linear loop? (Hint: a certain Stirling analysed $log n!$ ...)



      (Or, arguably cheating, there are only 21 decades in view, so you could hard-code a lookup.)






      share|improve this answer

























        up vote
        6
        down vote










        up vote
        6
        down vote










        import math
        n = int(input())
        while n != 0:
        n = (n - 1960) / 10 + 2



        What does n represent now? n as a name for the value which is called y in the task description is already unnecessarily obscure, but aliasing it really confuses things.



        In addition, note that in Python / does floating point division. If the output for 1969 should be the same as the output for 1960 (and I'm pretty sure the spec requires that) then there's a bug here.




         m = pow(2,n)



        What does m represent? If you want people to review your code, use descriptive names!




         while m > 0:
        m -= math.log(i,2)
        i += 1



        How many times does this loop execute for the largest possible input? How can you avoid a linear loop? (Hint: a certain Stirling analysed $log n!$ ...)



        (Or, arguably cheating, there are only 21 decades in view, so you could hard-code a lookup.)






        share|improve this answer
















        import math
        n = int(input())
        while n != 0:
        n = (n - 1960) / 10 + 2



        What does n represent now? n as a name for the value which is called y in the task description is already unnecessarily obscure, but aliasing it really confuses things.



        In addition, note that in Python / does floating point division. If the output for 1969 should be the same as the output for 1960 (and I'm pretty sure the spec requires that) then there's a bug here.




         m = pow(2,n)



        What does m represent? If you want people to review your code, use descriptive names!




         while m > 0:
        m -= math.log(i,2)
        i += 1



        How many times does this loop execute for the largest possible input? How can you avoid a linear loop? (Hint: a certain Stirling analysed $log n!$ ...)



        (Or, arguably cheating, there are only 21 decades in view, so you could hard-code a lookup.)







        share|improve this answer















        share|improve this answer



        share|improve this answer








        edited Jan 16 at 15:25


























        answered Jan 16 at 15:19









        Peter Taylor

        14.1k2454




        14.1k2454






















            up vote
            2
            down vote













            You need to use some maths.



            You want to know whether



            $n! < 2^b$ (where $b$ is the number of bits)



            This is equivalent of:



            $log n! lt log 2^b$

            $log n! lt blog 2$



            Then we need efficient $log n!$ calculation..



            $log n!$ = $log (n(n-1)!)$ = $log n + log (n-1)!$



            We can pre-compute the log n! for the first some n



            The maximum year = 2160, with equals a 4194304 bits computer.



            As I'm trying I see you need way to much pre-computed log n!, so we need a better way of calculating log n!. There exists an solution when log is chosen to be the natural logarithm ln:
            http://mathworld.wolfram.com/StirlingsApproximation.html



            It states:



            $ ln n! ≈ n ln n-n+1$ (for big n)



            so we need to solve:



            $ n ln n-n+1 < b ln 2$



            For small n we can still use a lookup table. You can determine where the error gets small enough to stop using the lookup-table.






            share|improve this answer























            • If $log$ is $log_2$, then you can use $log_2n! lt b$. Which is really fast and simple.
              – Peilonrayz
              Jan 16 at 15:13










            • Yes, but n! get really bit really fast, so need to find something smarter there yet. Probably log ab = log a + log b ;)
              – RobAu
              Jan 16 at 15:16






            • 1




              Do you realise that what you've done here is propose that OP make no changes to his code?
              – Peter Taylor
              Jan 16 at 15:23






            • 2




              I believe it is not, as I will never calculate the powers of 2 and get into the big numbers?
              – RobAu
              Jan 16 at 15:26










            • Nor does OP's code. (I agree that m = pow(2,n) looks like it's doing that, but it turns out to be calculating $b$).
              – Peter Taylor
              Jan 16 at 15:56














            up vote
            2
            down vote













            You need to use some maths.



            You want to know whether



            $n! < 2^b$ (where $b$ is the number of bits)



            This is equivalent of:



            $log n! lt log 2^b$

            $log n! lt blog 2$



            Then we need efficient $log n!$ calculation..



            $log n!$ = $log (n(n-1)!)$ = $log n + log (n-1)!$



            We can pre-compute the log n! for the first some n



            The maximum year = 2160, with equals a 4194304 bits computer.



            As I'm trying I see you need way to much pre-computed log n!, so we need a better way of calculating log n!. There exists an solution when log is chosen to be the natural logarithm ln:
            http://mathworld.wolfram.com/StirlingsApproximation.html



            It states:



            $ ln n! ≈ n ln n-n+1$ (for big n)



            so we need to solve:



            $ n ln n-n+1 < b ln 2$



            For small n we can still use a lookup table. You can determine where the error gets small enough to stop using the lookup-table.






            share|improve this answer























            • If $log$ is $log_2$, then you can use $log_2n! lt b$. Which is really fast and simple.
              – Peilonrayz
              Jan 16 at 15:13










            • Yes, but n! get really bit really fast, so need to find something smarter there yet. Probably log ab = log a + log b ;)
              – RobAu
              Jan 16 at 15:16






            • 1




              Do you realise that what you've done here is propose that OP make no changes to his code?
              – Peter Taylor
              Jan 16 at 15:23






            • 2




              I believe it is not, as I will never calculate the powers of 2 and get into the big numbers?
              – RobAu
              Jan 16 at 15:26










            • Nor does OP's code. (I agree that m = pow(2,n) looks like it's doing that, but it turns out to be calculating $b$).
              – Peter Taylor
              Jan 16 at 15:56












            up vote
            2
            down vote










            up vote
            2
            down vote









            You need to use some maths.



            You want to know whether



            $n! < 2^b$ (where $b$ is the number of bits)



            This is equivalent of:



            $log n! lt log 2^b$

            $log n! lt blog 2$



            Then we need efficient $log n!$ calculation..



            $log n!$ = $log (n(n-1)!)$ = $log n + log (n-1)!$



            We can pre-compute the log n! for the first some n



            The maximum year = 2160, with equals a 4194304 bits computer.



            As I'm trying I see you need way to much pre-computed log n!, so we need a better way of calculating log n!. There exists an solution when log is chosen to be the natural logarithm ln:
            http://mathworld.wolfram.com/StirlingsApproximation.html



            It states:



            $ ln n! ≈ n ln n-n+1$ (for big n)



            so we need to solve:



            $ n ln n-n+1 < b ln 2$



            For small n we can still use a lookup table. You can determine where the error gets small enough to stop using the lookup-table.






            share|improve this answer















            You need to use some maths.



            You want to know whether



            $n! < 2^b$ (where $b$ is the number of bits)



            This is equivalent of:



            $log n! lt log 2^b$

            $log n! lt blog 2$



            Then we need efficient $log n!$ calculation..



            $log n!$ = $log (n(n-1)!)$ = $log n + log (n-1)!$



            We can pre-compute the log n! for the first some n



            The maximum year = 2160, with equals a 4194304 bits computer.



            As I'm trying I see you need way to much pre-computed log n!, so we need a better way of calculating log n!. There exists an solution when log is chosen to be the natural logarithm ln:
            http://mathworld.wolfram.com/StirlingsApproximation.html



            It states:



            $ ln n! ≈ n ln n-n+1$ (for big n)



            so we need to solve:



            $ n ln n-n+1 < b ln 2$



            For small n we can still use a lookup table. You can determine where the error gets small enough to stop using the lookup-table.







            share|improve this answer















            share|improve this answer



            share|improve this answer








            edited Jan 16 at 15:46


























            answered Jan 16 at 15:03









            RobAu

            2,296817




            2,296817











            • If $log$ is $log_2$, then you can use $log_2n! lt b$. Which is really fast and simple.
              – Peilonrayz
              Jan 16 at 15:13










            • Yes, but n! get really bit really fast, so need to find something smarter there yet. Probably log ab = log a + log b ;)
              – RobAu
              Jan 16 at 15:16






            • 1




              Do you realise that what you've done here is propose that OP make no changes to his code?
              – Peter Taylor
              Jan 16 at 15:23






            • 2




              I believe it is not, as I will never calculate the powers of 2 and get into the big numbers?
              – RobAu
              Jan 16 at 15:26










            • Nor does OP's code. (I agree that m = pow(2,n) looks like it's doing that, but it turns out to be calculating $b$).
              – Peter Taylor
              Jan 16 at 15:56
















            • If $log$ is $log_2$, then you can use $log_2n! lt b$. Which is really fast and simple.
              – Peilonrayz
              Jan 16 at 15:13










            • Yes, but n! get really bit really fast, so need to find something smarter there yet. Probably log ab = log a + log b ;)
              – RobAu
              Jan 16 at 15:16






            • 1




              Do you realise that what you've done here is propose that OP make no changes to his code?
              – Peter Taylor
              Jan 16 at 15:23






            • 2




              I believe it is not, as I will never calculate the powers of 2 and get into the big numbers?
              – RobAu
              Jan 16 at 15:26










            • Nor does OP's code. (I agree that m = pow(2,n) looks like it's doing that, but it turns out to be calculating $b$).
              – Peter Taylor
              Jan 16 at 15:56















            If $log$ is $log_2$, then you can use $log_2n! lt b$. Which is really fast and simple.
            – Peilonrayz
            Jan 16 at 15:13




            If $log$ is $log_2$, then you can use $log_2n! lt b$. Which is really fast and simple.
            – Peilonrayz
            Jan 16 at 15:13












            Yes, but n! get really bit really fast, so need to find something smarter there yet. Probably log ab = log a + log b ;)
            – RobAu
            Jan 16 at 15:16




            Yes, but n! get really bit really fast, so need to find something smarter there yet. Probably log ab = log a + log b ;)
            – RobAu
            Jan 16 at 15:16




            1




            1




            Do you realise that what you've done here is propose that OP make no changes to his code?
            – Peter Taylor
            Jan 16 at 15:23




            Do you realise that what you've done here is propose that OP make no changes to his code?
            – Peter Taylor
            Jan 16 at 15:23




            2




            2




            I believe it is not, as I will never calculate the powers of 2 and get into the big numbers?
            – RobAu
            Jan 16 at 15:26




            I believe it is not, as I will never calculate the powers of 2 and get into the big numbers?
            – RobAu
            Jan 16 at 15:26












            Nor does OP's code. (I agree that m = pow(2,n) looks like it's doing that, but it turns out to be calculating $b$).
            – Peter Taylor
            Jan 16 at 15:56




            Nor does OP's code. (I agree that m = pow(2,n) looks like it's doing that, but it turns out to be calculating $b$).
            – Peter Taylor
            Jan 16 at 15:56












             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185210%2fquickest-way-of-finding-the-largest-integer-n-such-that-n-has-length-of-m-bits%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Chat program with C++ and SFML

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            Will my employers contract hold up in court?