I'm a beginner in Python, teaching myself off of Google Code University. I had this problem as an exercise, and was able to solve it using the solution shown below:
# F. front_back
# Consider dividing a string into two halves.
# If the length is even, the front and back halves are the same length.
# If the length is odd, we'll say that the extra char goes in the front half.
# e.g. 'abcde', the front half is 'abc', the back half 'de'.
# Given 2 strings, a and b, return a string of the form
# a-front + b-front + a-back + b-back
def front_back(a, b):
if len(a) % 2 == 0:
ad = len(a) / 2
if len(b) % 2 == 0:
bd = len(b) / 2
else:
bd = (len(b) / 2) + 1
else:
ad = (len(a) / 2) + 1
if len(b) % 2 == 0:
bd = len(b) / 2
else:
bd = (len(b) / 2) + 1
return a[:ad] + b[:bd] + a[ad:] + b[bd:]
This produces the correct output and solves the problem. However, I am duplicating the logic of whether to split a string evenly or add the odd number to the first half, and this seems redundant. There has to be a more efficient way of doing this. The same exact check and logic is being applied to a and b. Anyone?
def front_back(a, b):
ad = (len(a) + 1) // 2
bd = (len(b) + 1) // 2
return a[:ad] + b[:bd] + a[ad:] + b[bd:]
Using // for division makes this code work in both Python 2.x and 3.x.
Well, put it in a separate function.
def front_back(string):
offset = len(string) / 2
if len(string) % 2 != 0:
offset += 1
return string[:offset], string[offset:]
def solution(a, b):
front_a, back_a = front_back(a)
front_b, back_b = front_back(b)
return front_a + back_a + front_b + back_b
Since you're adding 1 to the length if it's odd, and 'odd' means that len(a)%2 == 1...
def front_back2(a, b):
ad = (len(a) + len(a)%2) / 2
bd = (len(b) + len(b)%2) / 2
return a[:ad]+b[:bd]+a[ad:]+b[bd:]
Of course, you could even condense it to one line just for kicks (although, it's significantly less readable):
def front_back2(a, b):
return a[:(len(a)+len(a)%2)/2]+b[:(len(b)+len(b)%2)/2]+a[(len(a)+len(a)%2)/2:]+b[(len(b)+len(b)%2)/2:]
You can get the maximum index by using ceil
In [1]: l = [1,2,3]
In [2]: import math
In [4]: math.ceil(len(l)/2.0)
Out[4]: 2.0
In [5]: l.append(4)
In [6]: math.ceil(len(l)/2.0)
Out[6]: 2.0
In [7]: l.append(5)
In [8]: math.ceil(len(l)/2.0)
Out[8]: 3.0
In [9]: l[0:3]
Out[9]: [1, 2, 3]
In [10]: l[3:]
Out[10]: [4, 5]
Mhh trying to understand #Sven answer I got this:
len( s ) + 1 / 2
Will always give you the correct index.
So if we put that in a function:
def d( s ):
return ( len(s) + 1 ) / 2
We can use it in the solution:
def front_back( a, b ):
return a[:d(a)] + b[:d(b)] + a[d(a):] + b[d(b):]
Ok, I got it now.
I'm not quite sure what's the difference between / and // though
from math import ceil
def front_back(a, b):
divide = lambda s: int(ceil(len(s) / 2.0)) # or lambda s: (len(s) + 1) // 2
a_divide, b_divide = divide(a), divide(b)
return a[:a_divide] + b[:b_divide] + a[a_divide:] + b[b_divide:]
Here's mine:
def front_back( a, b ) :
return of(a)[0] + of(b)[0] + of(a)[1] + of(b)[1]
def of( s ):
index = len( s ) / 2 + ( 1 if len( s ) % 2 == 1 else 0 )
return ( s[ : index ] , s[ index : ] )
print front_back('abcde','hola')
Prints:
abchodela
Related
I need help for defining the fibanocci 2 function. The fibanocci 2 function is decribed as :
fib2(n) = {0 if n <= 0, 1 if n = 1, 2 if n = 2, ( fib2( n - 1) * fib2( n - 2)) - fib2( n - 3) else}
We need to define this function iterative.
I tried my best but i couldn't write a working code.
def fib2(n: int) -> int:
if n <= 0:
return 0
elif n == 1:
return 1
elif n == 2:
return 2
else:
n = ((n - 1) * (n - 2) - (n - 3)
return n
a = fib2(7)
print (a)
assert (fib2(7) == 37)
the output from this fib2 function is 26 but it should be 37.
Thank you in advance
For the iterative version you have to use a for loop.
And just add the 3 previous numbers to get the next one.
Here is a piece of code:
def fib3(n):
a = 0
b = 1
c = 0
for n in range(n):
newc = a+b+c
a = b
b = c
c = newc
return newc
print(fib3(7))
assert (fib3(7) == 37)
You can not change the value of a parameter.
Please try to return directly :
Return ((fb2(n-1)×fb2(n-2))-fb2(n-3))
So it will work as a recursive function.
def fibo(n):
current = 0
previous_1 = 1
previous_2 = 0
for i in range(1,n):
current = previous_1 + previous_2
previous_2 = previous_1
previous_1 = current
return current
To do it iteratively, the best way is to write it on paper to understand how it works.
Mathematically fibo is Fn = Fn-1 + Fn-2 . Therefore, you can create variables called previous_1 and previous_2 which represents the elements of Fn and you simply update them on each run.
Fn is current
I'm a bit stuck on a python problem.
I'm suppose to write a function that takes a positive integer n and returns the number of different operations that can sum to n (2<n<201) with decreasing and unique elements.
To give an example:
If n = 3 then f(n) = 1 (Because the only possible solution is 2+1).
If n = 5 then f(n) = 2 (because the possible solutions are 4+1 & 3+2).
If n = 10 then f(n) = 9 (Because the possible solutions are (9+1) & (8+2) & (7+3) & (7+2+1) & (6+4) & (6+3+1) & (5+4+1) & (5+3+2) & (4+3+2+1)).
For the code I started like that:
def solution(n):
nb = list(range(1,n))
l = 2
summ = 0
itt = 0
for index in range(len(nb)):
x = nb[-(index+1)]
if x > 3:
for index2 in range(x-1):
y = nb[index2]
#print(str(x) + ' + ' + str(y))
if (x + y) == n:
itt = itt + 1
for index3 in range(y-1):
z = nb[index3]
if (x + y + z) == n:
itt = itt + 1
for index4 in range(z-1):
w = nb[index4]
if (x + y + z + w) == n:
itt = itt + 1
return itt
It works when n is small but when you start to be around n=100, it's super slow and I will need to add more for loop which will worsen the situation...
Do you have an idea on how I could solve this issue? Is there an obvious solution I missed?
This problem is called integer partition into distinct parts. OEIS sequence (values are off by 1 because you don't need n=>n case )
I already have code for partition into k distinct parts, so modified it a bit to calculate number of partitions into any number of parts:
import functools
#functools.lru_cache(20000)
def diffparts(n, k, last):
result = 0
if n == 0 and k == 0:
result = 1
if n == 0 or k == 0:
return result
for i in range(last + 1, n // k + 1):
result += diffparts(n - i, k - 1, i)
return result
def dparts(n):
res = 0
k = 2
while k * (k + 1) <= 2 * n:
res += diffparts(n, k, 0)
k += 1
return res
print(dparts(201))
Can you explain it what problems are here? To my mind, this code is like a heap of crap but with the right solving. I beg your pardon for my english.
the task of this kata:
Some numbers have funny properties. For example:
89 --> 8¹ + 9² = 89 * 1
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:
Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k
If it is the case we will return k, if not return -1.
Note: n, p will always be given as strictly positive integers.
dig_pow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
dig_pow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
dig_pow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
dig_pow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
def dig_pow(n, p):
if n > 0 and p > 0:
b = []
a = str(n)
result = []
for i in a:
b.append(int(i))
for x in b:
if p != 1:
result.append(x ** p)
p += 1
else:
result.append(x ** (p + 1))
if int((sum(result)) / n) < 1:
return -1
elif int((sum(result)) / n) < 2:
return 1
else:
return int((sum(result)) / n)
test results:
Test Passed
Test Passed
Test Passed
Test Passed
3263 should equal -1
I don't know what exact version of Python you're using. This following code are in Python 3. And if I get you correctly, the code can be as simple as
def dig_pow(n, p):
assert n > 0 and p > 0
digits = (int(i) for i in str(n)) # replaces your a,b part with generator
result = 0 # you don't use result as a list, so an int suffice
for x in digits: # why do you need if in the loop? (am I missing something?)
result += x ** p
p += 1
if result % n: # you just test for divisibility
return -1
else:
return result // n
The major problem is that, in your objective, you have only two option of returning, but you wrote if elif else, which is definitely unnecessary and leads to problems and bugs. The % is modulus operator.
Also, having an if and not returning anything in the other branch is often not a good idea (see the assert part). Of course, if you don't like it, just fall back to if.
I believe this could work as well and I find it a little easier to read, however it can definitely be improved:
def dig_pow(n, p):
value = 0
for digit in str(n):
value += int(digit)**p
p += 1
for k in range(1,value):
if value/k == n:
return k
return -1
this is some example simple example than using:
digits = (int(i) for i in str(n))
I'm opting to use this version since I am still a beginner which can be done with this alt way:
result = 0
for digits in str(n):
#iterate through each digit from n
# single of digits turn to int & power to p
for number in digits:
result += int(number) ** p
p += 1
as for the full solution, it goes like this:
def dig_pow(n, p):
# example n = 123 , change it to string = 1, 2, 3
# each string[] **p, and p iterate by 1
# if n % p not equal to p return - 1
result = 0
for digits in str(n):
#iterate through each digit from n
# single digit turn to int & power to p
for number in digits:
result += int(number) ** p
p += 1
if result % n:
return -1
else:
return result // n
So I have a function that takes two string inputs - it slices them so that if of even length, the length of the front segment is the same as that of the back, and if of odd length, the middle character goes to the front segment (i.e. hello -> hel , lo). And then you mix and match the resulting front and back segments of the two string to produce the final output.
I want to be able to do this all under one function and what I came up with is ugly as all heck:
def front_back(a, b):
if len(a) % 2 == 0:
front_a = a[:len(a)/2]
back_a = a[len(a)/2:]
elif len(a) % 2 != 0:
front_a = a[:(len(a)/2)+1]
back_a = a[(len(a)/2)+1:]
if len(b) % 2 == 0:
front_b = b[:len(b)/2]
back_b = b[len(b)/2:]
elif len(b) % 2 != 0:
front_b = b[:(len(b)/2)+1]
back_b = b[(len(b)/2)+1:]
print front_a + front_b + back_a + back_b
front_back('Kitten', 'Donut') ---> KitDontenut
Is there a more pythonic/elegant way?
I couldn't figure out how to use lambdas (they can't process the if statement necessary to deal with even and odd length cases... i think?) if that's the way to go...
UPDATE:
thanks for the great suggestions everyone. just one more question:
when i try a version with lamdbas, based off a suggestion (for practice), I get a NameError that global name 's' isn't defined. What's wrong with how I wrote the lambda?
def front_back(a, b):
divideString = lambda s: s[:((1+len(s))//2)], s[((1+len(s))//2):]
a1, a2 = divideString(a)
b1, b2 = divideString(b)
print a1 + b1 + a2 + b2
front_back("hello","cookies")
You are making it more complicated than it needs to be:
def front_back(a, b):
mid_a, mid_b = (len(a) + 1) // 2, (len(b) + 1) // 2
front_a, back_a = a[:mid_a], a[mid_a:]
front_b, back_b = b[:mid_b], b[mid_b:]
print front_a + front_b + back_a + back_b
By adding 1 before dividing by 2 (floor division), you round up.
Demo:
>>> def front_back(a, b):
... mid_a, mid_b = (len(a) + 1) // 2, (len(b) + 1) // 2
... front_a, back_a = a[:mid_a], a[mid_a:]
... front_b, back_b = b[:mid_b], b[mid_b:]
... print front_a + front_b + back_a + back_b
...
>>> front_back('Kitten', 'Donut')
KitDontenut
You could inline the slicing even:
def front_back(a, b):
mid_a, mid_b = (len(a) + 1) // 2, (len(b) + 1) // 2
print a[:mid_a] + b[:mid_b] + a[mid_a:] + b[mid_b:]
def divideString(myString):
sliceHere = ( (1 + len(myString)) // 2)
return myString[:sliceHere], myString[sliceHere:]
def front_back(a, b):
a1, a2 = divideString(a)
b1, b2 = divideString(b)
return a1 + b1 + a2 + b2
def front_back(a, b):
return "".join([a[:(len(a)+1)/2]], b[:(len(b)+1)/2], \
a[(len(a)+1)/2]:], b[:(len(b)+1)/2]])
You could also add the result of length % 2 to the fronts:
def front_back(a, b):
ln_a, ln_b = len(a), len(b)
a1 = a2 = ln_a // 2
b1 = b2 = ln_b // 2
a1 += ln_a % 2
b1 += ln_b % 2
return a[:a1] + b[:b1] + a[-a2:] + b[-b2:]
print(front_back('Kitten', 'Donut'))
There are a some good answers here already, but for the sake of diversity, since you seem to be interested in multiple possibilities, here's a different way of looking at it:
import itertools
def front_back(a,b):
words = [a,b]
output = [[],[]]
for word in words:
if len(word) % 2 == 0:
output[0].append(word[:len(word)//2])
output[1].append(word[len(word)//2:])
else:
output[0].append(word[:len(word)//2+1])
output[1].append(word[(len(word)//2)+1:])
return "".join(output[0]) + "".join(output[1])
print(front_back('Kitten', 'Donut'))
Interpret with Python 3.
I've done the exercise and it works. But I want to know if there a smarter way to do it. Thanks.
# Consider dividing a string into two halves.
# If the length is even, the front and back halves are the same length.
# If the length is odd, we'll say that the extra char goes in the front half.
# e.g. 'abcde', the front half is 'abc', the back half 'de'.
# Given 2 strings, a and b, return a string of the form
# a-front + b-front + a-back + b-back
My code:
def front_back(a, b):
if len(a) % 2 == 0:
a_front = a[0:len(a) / 2]
else:
a_front = a[0:(len(a) / 2) + 1]
if len(a) % 2 == 0:
a_back = a[len(a) / 2:]
else:
a_back = a[(len(a) / 2) + 1:]
if len(b) % 2 == 0:
b_front = b[0:len(b) / 2]
else:
b_front = b[0:(len(b) / 2) + 1]
if len(b) % 2 == 0:
b_back = b[len(b) / 2:]
else:
b_back = b[(len(b) / 2) + 1:]
return a_front + b_front + a_back + b_back
You probably don't need all the if tests. Using substrings (as you use the slices in python), the following example in Java works.
public static String SplitMixCombine(String a, String b) {
return a.substring(0, (a.length()+1)/2) +
b.substring(0, (b.length()+1)/2) +
a.substring((a.length()+1)/2, a.length()) +
b.substring((b.length()+1)/2, b.length());
}
Just got this to work in python:
>>> def mix_combine(a, b):
... return a[0:int((len(a)+1)/2)] + b[0:int((len(b)+1)/2)] + a[int((len(a)+1)/2):] +b[int((len(b)+1)/2):]
...
>>> a = "abcd"
>>> b = "wxyz"
>>> mix_combine(a,b)
'abwxcdyz'
>>> a = "abcde"
>>> b = "vwxyz"
>>> mix_combine(a,b)
'abcvwxdeyz'
>>>
This is a lot cleaner code.
def front_back(a, b):
print a, b
a_indx = int((len(a)+1)/2)
b_indx = int((len(b)+1)/2)
print a[:a_indx] + b[:b_indx] + a[a_indx:] +b[b_indx:]
print "\n"
front_back("ab", "cd")
front_back("abc", "de")
front_back("ab", "cde")
front_back("abc", "def")
Hope this helps !
I wrote another one-liner for this:
def front_back(a, b):
return a[:len(a) / 2 + len(a) % 2] + b[:len(b) / 2 + len(b) % 2] + a[-(len(a) / 2):] + b[-(len(b) / 2):]
An interesting thing to note is that in Python 5 / 2 yields 2, but -5 / 2 yields -3, you might expect to get -2. That's why I added the parenthesis. See Negative integer division surprising result
def front_back(a, b):
return front_string(a)+front_string(b)+back_string(a)+back_string(b)
def front_string(s):
return s[:int((len(s)+1)/2)]
def back_string(s):
return s[int((len(s)+1)/2):]
# int((len(s)+1)/2) returns the correct index for both odd and even length strings