Python Fewest Lines Challenge (HOTPO/Collatz) - python

The Collatz Conjecture, otherwise known as Half Or Triple Plus One (HOTPO), takes any positive integer n to start.
If n is even, divide it by two. If n is odd, multiply it by 3 and add 1. The conjecture is that no matter what number you start with, it will always reach 1.
The challenge is to write a program that outputs all the values of n as well as the number of steps it took. For example, with n = 3, the output should be:
3
10
5
16
8
4
2
1
Finished. 7 steps required.
My best attempt takes 6 lines:
x = [3]
while x[-1] != 1:
if x[-1] % 2 == 1: x.append(3*x[-1]+1)
x.append(x[-1]/2)
for num in x: print num
print "Finished. " + str(len(x)-1) + " steps needed."
What is the minimum number of lines required to generate this output for any reasonably-sized n? Can my code be further reduced?

Some improvements making use of the lambda function:
x=[3]
while x[-1] != 1:
x.append((lambda n: n%2==0 and n/2 or 3*n+1)(x[-1]))
print(x[-1])
print "Finished. " + str(len(x)-1) + " steps needed."
I just stick more code in one line, and there is now only one loop instead of two, printing can be done from the same loop as calculating.
Or since it is for least number of lines, you can use two one line loops and get it in 3 lines:
x=[3]
while x[-1]!=1: x=(lambda y: y+[(lambda n: n%2==0 and n/2 or 3*n+1)(x[-1])])(x)
print("\n".join([str(y) for y in x])+"\nFinished. {} steps required.".format(len(x)-1))
With thanks to Pythonista for that last line :)

Another way to write it in three lines without the use of lambda function because they are unnecessary for a variable that can be referenced.
x = [3]
while x[-1] != 1:x.append((3*x[-1]+1) if x[-1] % 2 == 1 else (x[-1]/2))
print("\n".join([str(num) for num in x])+"\nFinished. " + str(len(x)-1) + " steps needed.")

Related

Is ther any other way to get sum 1 to 100 with recursion?

I'm studing recursive function and i faced question of
"Print sum of 1 to n with no 'for' or 'while' "
ex ) n = 10
answer =
55
n = 100
answer = 5050
so i coded
import sys
sys.setrecursionlimit(1000000)
sum = 0
def count(n):
global sum
sum += n
if n!=0:
count(n-1)
count(n = int(input()))
print(sum)
I know it's not good way to get right answer, but there was a solution
n=int(input())
def f(x) :
if x==1 :
return 1
else :
return ((x+1)//2)*((x+1)//2)+f(x//2)*2
print(f(n))
and it works super well , but i really don't know how can human think that logic and i have no idea how it works.
Can you guys explain how does it works?
Even if i'm looking that formula but i don't know why he(or she) used like that
And i wonder there is another solution too (I think it's reall important to me)
I'm really noob of python and code so i need you guys help, thank you for watching this
Here is a recursive solution.
def rsum(n):
if n == 1: # BASE CASE
return 1
else: # RECURSIVE CASE
return n + rsum(n-1)
You can also use range and sum to do so.
n = 100
sum_1_to_n = sum(range(n+1))
you can try this:
def f(n):
if n == 1:
return 1
return n + f(n - 1)
print(f(10))
this function basically goes from n to 1 and each time it adds the current n, in the end, it returns the sum of n + n - 1 + ... + 1
In order to get at a recursive solution, you have to (re)define your problems in terms of finding the answer based on the result of a smaller version of the same problem.
In this case you can think of the result sumUpTo(n) as adding n to the result of sumUpTo(n-1). In other words: sumUpTo(n) = n + sumUpTo(n-1).
This only leaves the problem of finding a value of n for which you know the answer without relying on your sumUpTo function. For example sumUpTo(0) = 0. That is called your base condition.
Translating this to Python code, you get:
def sumUpTo(n): return 0 if n==0 else n + sumUpTo(n-1)
Recursive solutions are often very elegant but require a different way of approaching problems. All recursive solutions can be converted to non-recursive (aka iterative) and are generally slower than their iterative counterpart.
The second solution is based on the formula ∑1..n = n*(n+1)/2. To understand this formula, take a number (let's say 7) and pair up the sequence up to that number in increasing order with the same sequence in decreasing order, then add up each pair:
1 2 3 4 5 6 7 = 28
7 6 5 4 3 2 1  = 28
-- -- -- -- -- -- -- --
8 8 8 8 8 8 8 = 56
Every pair will add up to n+1 (8 in this case) and you have n (7) of those pairs. If you add them all up you get n*(n+1) = 56 which correspond to adding the sequence twice. So the sum of the sequence is half of that total n*(n+1)/2 = 28.
The recursion in the second solution reduces the number of iterations but is a bit artificial as it serves only to compensate for the error introduced by propagating the integer division by 2 to each term instead of doing it on the result of n*(n+1). Obviously n//2 * (n+1)//2 isn't the same as n*(n+1)//2 since one of the terms will lose its remainder before the multiplication takes place. But given that the formula to obtain the result mathematically is part of the solution doing more than 1 iteration is pointless.
There are 2 ways to find the answer
1. Recursion
def sum(n):
if n == 1:
return 1
if n <= 0:
return 0
else:
return n + sum(n-1)
print(sum(100))
This is a simple recursion code snippet when you try to apply the recurrent function
F_n = n + F_(n-1) to find the answer
2. Formula
Let S = 1 + 2 + 3 + ... + n
Then let's do something like this
S = 1 + 2 + 3 + ... + n
S = n + (n - 1) + (n - 2) + ... + 1
Let's combine them and we get
2S = (n + 1) + (n + 1) + ... + (n + 1) - n times
From that you get
S = ((n + 1) * n) / 2
So for n = 100, you get
S = 101 * 100 / 2 = 5050
So in python, you will get something like
sum = lambda n: ( (n + 1) * n) / 2
print(sum(100))

Having trouble understanding this recursion function

I was reviewing the topic of recursion in a tutorial site and came across the problem and solution below:
Problem:
Given an integer, create a function which returns the sum of all the individual digits in that integer. For example: if n = 4321, return 10 since 4+3+2+1=10.
Solution:
def sum_func(n):
if n<10:
return n
else:
return n%10 + sum_func(int(n/10))
pass
I understand the "if n<10" is the base case - if n is single digit, then just return n. What I couldn't wrap my head around is the "n%10 + sum_func(int(n/10))" line of code. Assume n is 235, n%10 will equal 5 and int(n/10) will equal 23. Then ultimately 5 + 23 will become 28 and not 10.
Could someone please help me understand what "n%10 + sum_func(int(n/10))" does? If you could walk through the logic one line at a time that would be greatly appreciated!
if n = 235 then int(n/10) is 23. However, you do not add 5 and 23. You add sum_func(int(n/10)) and 5.
sum_func(int(n/10)) is not int(n/10)
sum_func(int(n/10)) adds the digits in the number "23" together.
As such, sum_func(int(n/10)) == 2 + 3 == 5
sum_func(235) == sum_func(235)
== sum_func(23) + 5
== sum_func(2) + 3 + 5
== 2 + 3 + 5
As you say if there's only 1 digit return it.
The % is the modulus operator - i.e. the remainder when dividing by 10, or simply the last digit (i.e. 235%10 = 5)
int(n/10) drops the last digit since the int() function rounds down - i.e. 235 -> 23
Now what you seem to be confused by is within sum_func it calls sum_func again with the remainder once the last digit has been dropped i.e. 23 (this is the recursion part) which will then return 5.
i.e. you have
sum_func(235)
=5 + sum_func(23)
=5 + (3 + sum_func(2))
=5 + (3 + (2))
=10

Is there a fast method for comparing values of 2 lists up to a specified index in Python 3?

I want to know how to automate this part:
if n + list1[0] == list2[0] and n + list1[1] == list2[1] and n + list1[2] == list2[2]:
In this code:
def find_first_match(amount_of_checks):
for n in range(range_start, range_end):
if n + list1[0] == list2[0] and n + list1[1] == list2[1] and n + list1[2] == list2[2]:
first_match = n
return first_match
Meaning perform specified amount of n + list1[index] == list2[index] checks automatically, instead of manually hard-coding those 3 comparing statements in there. And not loose any performance?
I tried to replace this hard-coded if statement with this code down below, but it's a few times slower than the hardcoded way:
if all((n + a == b) for a, b in zip(list1[:amount_of_checks], list2[:amount_of_checks])):
So is there a way to:
make it not hard-coded (use a variable's value to generate specified amount of check)
retain performance
Update:
The first list is always the same, the second list always has random values, so I want it to go through the specified range of numbers n (100, 101, 102, ...) and find the first n that would satisfy ALL the checks (find the 2nd list that has the same values as the first list)
I want it to work with all the operations, like +,-,*,/,% etc
if all((n % a == b) for a, b in zip(list1[:amount_of_checks], list2[:amount_of_checks]))
This code is slow because the slices list1[:amount_of_checks] and list2[:amount_of_checks] iterate amount_of_checks times to create sublists that get thrown away. It's particularly unfortunate when (n % a == b) evaluates to False on an early iteration because all is happy to shorcut evaluation in these situations, but you've already paid the performance penalty in the sublist creation.
Use itertools.islice to avoid the performance penalty of creating the sublists:
zip(islice(list1, amount_of_checks), islice(list2, amount_of_checks))
This can be streamlined by switching the order or zip and islice
islice(zip(list1, list2), amount_of_checks)
Put it all together and you get
if all((n % a == b) for a, b in islice(zip(list1, list2), amount_of_checks))
I think you are missing a key point here. You do not need to guess the size of your delta. You can rearrange n + list1[x] == list2[x] to read n == list2[x] - list1[x]. This way, there is only one or no values of n which make all the elements you want to compare equal to each other. You can do something like:
def find_n(amount_of_checks, list1, list2):
deltas = set(a - b for a, b in zip(list1[:amount_of_checks], list2[:amount_of_checks]))
if len(deltas) == 1:
return next(deltas)
This is a very simplified approach. One improvement that might help with performance would be to use itertools.islice instead of the index [1:amount_of_checks] since that would avoid allocating a new pair of lists.
Your original code only allows n within a certain range. If this is something you want and not just an artifact, you can add that test as well:
def find_n(amount_of_checks, list1, list2, n_start, n_end):
deltas = set(b - a for a, b in zip(list1[1:amount_of_checks], list2[1:amount_of_checks]))
if len(deltas) == 1:
n = next(deltas)
if n >= n_start and n < n_end:
return next(deltas)
Update in response to your update
You should be able to write all the operations besides modulo in the same way:
For n - list1[x] == list2[x], use deltas = set(a + b ...
For n * list1[x] == list2[x], use deltas = set(b / a ...
For n / list1[x] == list2[x], use deltas = set(b * a ...
For n**list1[x] == list2[x], use deltas = set(b ** (1 / a) ...
etc.
The problem with modulo is that it does not have a unique inverse operation. I do not remember enough number theory at this point to say if there will be a faster solution than just using #Steven's answer using a direct application of all, islice and zip, but I suspect not.
Use the builtin all function
if all(list1[i]-list2[i]==n for i in range(start, end)):
# Whatever you want to do
if all([(n + list1[i] == list2[i]) for i in range(start, end)]):
# ...
Just change start and end according to your range
However, of course this isn't quite as fast as writing out all the conditions by hand. If we measure execution time using timeit with some sample values, it becomes obvious:
timeit.timeit('all([(2 + 1 == 3) for _ in range(0, 5)])', number=10000)
> 0.008927443002903601
timeit.timeit('2 + 1 == 3 and 2 + 1 == 3 and 2 + 1 == 3 and 2 + 1 == 3 and 2 + 1 == 3', number=10000)
> 0.0011130370003229473
so keep that in mind (since I don't know how high your performance needs are)

SPOJ The Next Palindrome

I am trying to solve SPOJ problem 5: find the next largest integer "palindrome" for a given input; that is, an integer that in decimal notation reads the same from left-to-right and right-to-left.
Please have a look of the question here
Instead of using brute force search, I try to calculate the next palindrome. But my code still returns TLE (that is, Time Limit Exceeded) and I am frustrated... Would you mind giving me a hint?
Here is my code in python 3.x
if __name__ == '__main__':
n = int(input())
for i in range(n):
string = input()
length = len(string)
ans = ""
if length %2 == 0 :
half = length // 2
str_half = string[0:half]
ans = str_half + str_half[::-1]
if(ans <= string):
str_half = str(int(str_half) + 1)
ans = str_half + (str_half[0:half])[::-1]
print(ans)
else:
half = length // 2
str_half = string[0:half]
ans = str_half + string[half] + str_half[::-1]
if(ans<= string):
str_half = str(int(str_half+string[half]) + 1)
ans = str_half + (str_half[0:half])[::-1]
print(ans)
The input can be long. The problem statement says "not more than 1000000 digits". So probably there are a couple of test cases with several hundred thousand digits. Splitting such a string in halves, reversing one half and appending them does take a little time. But as far as I know, Python's string handling is pretty good, so that's only a small contribution to the problem.
What is taking a long time is converting strings of such length to numbers and huge numbers to strings. For K = 10 ** 200000 + 2, the step str_half = str(int(str_half+string[half]) + 1) alone took almost a second here. It may be faster on your computer, but SPOJ's machines are quite slow, one such occurrence may push you over the time limit there.
So you have to avoid the conversions, work directly on the string representations (mutable lists of digits).
So based on that problem lets figure out what the longest palindrome is for the case where K.length == 1 . This case can be safely ignored as there is no value larger than K that is a palindrome of K . The same applies to K.length == 2 . Therefore the pseudocode to evaluate this looks as follows:
if K.length <= 2
pass
When K.length == 3 the values we care about are K[0] and K[2] this gives us the boundaries. For example K == 100 . the values we care about are 1 and 0 . If K[0] is larger than K[2] we know that we must make K[2] = K[0] and we are done. Another example is K == 200 the first value larger is 202 which is the first prime that is equal. If K[0] == K[2] and K < 999, we increment K[1] by 1 and we are done. Pseudocode as follows:
if K[0] > K[2]
K[2] = K[0]
if K[0] == K[2] and K < 999
K[1]++
If all values in K are 9 (999,9999, etc) increment K by 2 and end the process.
I will leave the general form of the algorithm to you, unless you are ultimately stuck.

Fibonacci under 4 millions [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Python program to find fibonacci series. More Pythonic way.
Hey, i was trying to write a script which sums all the even terms in "Fibonacci Sequence" under 4 millions.
Fibonacci1 = 1
Fibonacci2 = 2
a = 2
i = 4
for i in range(1,4000000):
Fibonacci1 = Fibonacci1 + Fibonacci2
if Fibonacci1 % 2 == 0:
a = a + Fibonacci1
Fibonacci2 = Fibonacci1 + Fibonacci2
if Fibonacci2 % 2 == 0:
a = a + Fibonacci2
print a
raw_input()
it should takes less than a minute, but it took all night and it wasn't solved !
Edit: Sorry guys, i misunderstood the problem. I though it means that i have to sum all the even terms UP TO 4 million ! But the solution was to sum all the even terms UNTIL 4 million.
Working code (finished in less than one second):
Fibonacci1 = 1
Fibonacci2 = 2
a = 2
while a < 4000000:
Fibonacci1 = Fibonacci1 + Fibonacci2
if Fibonacci1 % 2 == 0:
a = a + Fibonacci1
Fibonacci2 = Fibonacci1 + Fibonacci2
if Fibonacci2 % 2 == 0:
a = a + Fibonacci2
print a
raw_input()
There are a couple of problems with your code:
You are looping four million times instead of until a condition is true.
You have repeated code in the body of your loop.
Most people when they start learning Python learn only imperative programming. This is not surprising because Python is an imperative language. But Python also supports functional programming to a certain extent and for this sort of exercise a functional programming approach is more enlightening in my opinion.
First define a generator that generates all the Fibonacci numbers:
def fib():
a = b = 1
while True:
yield a
a, b = b, a + b
To use this generator we can import a few useful functions from itertools. To print the first few numbers use islice:
from itertools import ifilter, islice, takewhile
for x in islice(fib(), 5):
print x
1
1
2
3
5
To find only the even numbers we can use ifilter to produce a new generator:
def is_even(x):
return x % 2 == 0
evenfibs = ifilter(is_even, fib())
for x in islice(evenfibs, 5):
print x
2
8
34
144
610
To fetch numbers from the generator until a number exceeds four million use takewhile:
for x in takewhile(lambda x: x < 4000000, evenfibs):
print x
To solve the problem you can use sum:
sum(list(takewhile(lambda x: x < 4000000, evenfibs)))
I hope this shows that a functional programming approach is not difficult and is a more elegant way to solve certain types of problem.
Are you sure it is i that you want to be less than 4 million?
You may be interested in knowing about the The On-Line Encyclopedia of Integer Sequences!
You can search information by name or by sequence.
If you search either for 0,2,8,34 or 'Even Fibonacci' you will be redirect to sequence A014445
There you you find lots of information including formulas,
from that to code a generator that will yield the even fibonacci numbers directly is easy.
def evenfib():
""" Generates the even fibonacci numbers """
a, b = 2, 0
while True:
a, b = b, a+4*b
yield a
The loop condition is wrong, it should be something like this:
while True:
Fibonacci1 = Fibonacci1 + Fibonacci2
if Fibonacci1 % 2 == 0:
if a + Fibonacci1 > 4000000:
break
a = a + Fibonacci1
Fibonacci2 = Fibonacci1 + Fibonacci2
if Fibonacci2 % 2 == 0:
if a + Fibonacci2 > 4000000:
break
a = a + Fibonacci2
Currently, you sum up all the first 2 million even Fibonacci numbers.
But that is not the task. You have to sum all even Fibonacci numbers that are below 4 million.
NOTE: This has been heavily modified to address the actual question
Here's an alternate (and very fast, but untested, method).
It relies on a few properties:
Each Fibonacci number can be calculated directly as floor( pow( phi, n ) + 0.5 ) (See Computation by Rounding in http://en.wikipedia.org/wiki/Fibonacci_number ). Conversely the index of the biggest Fibonacci number less than i is given by floor( log(i*sqrt(5)) / log(phi) )
The sum of the first N Fibonacci numbers is the N+2th fibonacci number minus 1 (See Second Identity on the same wikipedia page)
The even Fibonacci numbers are are every third number. ( Look at the sequence mod 2 and the result is trivial )
The sum of the even Fibonacci numbers is half the sum of the odd Fibonacci numbers upto the same point in the sequence. (This follows from 3. and the property that F(3N) = F(3N-1) + F(3N-2) so F(3N-2) + F(3N-1) + F(3N) = 2 F(N) .. then summing both sides.
So convert our maximum value of 4000000 calculate the index of the highest Fibonacci number
less than it.
int n = floor(log(4000000*sqrt(5))/log(phi)) = 33.
33 is divisible by 3 so it is an even Fibonacci number, if it wasn't we'd need to adjust n like this.
n = (n/3)*3
The sum of all Fibonacci numbers up to this point if given by
sum = floor( pow( phi, n+2 )/sqrt(5) + 0.5 ) - 1 = 9227464
The sum of all even numbers is half of this:
sum_even = 4613732
Nice thing about this is that its an O(1) (or O(log(N)) if you include the cost of pow/log) algorithm, and works on doubles.. so we can calculate the sum for very large values.
I don't exactly understand your algorithm, but it seems that smerriman has a point, 4000000 Fibonnacci sequence numbers would surely grow above 4M. I guess that the faster approach would be to generate sequence up to 4M, then adding up the even ones.
There are other tricks that make this more efficient than simply computing the complete list of Fibonacci numbers, and then summing the even numbers in the list.
I would, IF it were me trying to solve this problem, make a list of the even Fibonacci numbers. Are there any interesting characteristics of that list? Can you convince yourself that this pattern holds true in general?
Next, I might look for a way to compute the members of that list, and only those elements that are needed. I might even look to see if there are any formulas to be found that yield the sum of a sequence of Fibonacci numbers.
Of course, all of this would take up more of your own time than simply coding up the brute force solution, but Project Euler is all about finding the pretty solution rather than the brute force solution. In the end, if you have learned something about mathematics, about computation, then you have gained.
## nice simple generator Mark Byers
def fib():
a = b = 1
while True:
yield a
a, b = b, a + b
## does same as takewhile 5
for fibonacci in zip(range(1,1+5),fib()):
print "fib(%i) = %i" % fibonacci
## we can slice to take every second
print "even sequence upto 100th"
total=0
for fibonacci in zip(range(1,1+100),fib())[::2]:
print "fib(%i) = %i" % fibonacci
total+=fibonacci[1] ## to double check
print "Has sum: ", sum( b for a,b in zip(range(1,1+100),fib())[::2] ),'that is ',total
print "odd sequence upto 100th"
total=0
for fibonacci in zip(range(1,1+100),fib())[1::2]:
print "fib(%i) = %i" % fibonacci
total+=fibonacci[1] ## to double check
print "Has sum: ", sum( b for a,b in zip(range(1,1+100),fib())[1::2] ),'that is ',total
Come on, the optimal way to compute Fibonacci sequence is using 2 tricks:
EDITED, sorry for earlier mistake
1:
N =|2 0 0|
|1 0 0|
|0 0 0|
M =|3 2 1|
|2 1 0|
|0 0 1|
Matrix N*M^(n/3) has sum of first n fibonacci numbers (filtered only to the even ones) is the upper right element.
2:
You can use http://en.wikipedia.org/wiki/Exponentiation_by_squaring, because matrix multiplication is a ring.
So you can solve our problem in O(log n)

Categories