Python algorithm Golomb - python

program must find Sum(n)
G1+G2+G3+...+Gn
I wrote the program in python. It is working when I run. but if i send program to testing in site, 4 tests success, 5-th fails
my code:
import math
n = int(input())
k = 0
result = 0
while n > 0:
k += 1
num = (math.floor(k / 2) + 1)
sum_of_nums = num * k
n -= num
result += sum_of_nums
result += n * k
print(int(result))
first 25 numbers: [1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, ...]
1 = (floor(k / 2) + 1) * k k = 1
2 + 2 = (floor(k / 2) + 1) * k k = 2
3 + 3 = (floor(k / 2) + 1) * k k = 3
4 + 4 + 4 = (floor(k / 2) + 1) * k k = 4
...
result += n * k. this code removes from result (n may be < 0 or =0)

Here is a simple iterative way to generate the Golomb sequence:
n = 25
ns = [1]
for i in range(n-1):
ns.append(1+ns[i+1-ns[ns[-1]-1]])
ns
Output:
>>> ns
[1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9]
>>> sum(ns)
140
NB. I think your example in incorrect

Related

Use clipping or zero padding

Write a function that accept an array of N elements, and converts it into a 9-element array. Use clipping or zero padding to obtain the desired output. Care should be taken to place the middle element of the input array as the middle element of output array.
Examples
A = [ 2, 5, 1 ] # N == 3, so zero padding to make the output size 9
output = [0, 0, 0, 2, 5, 1, 0, 0, 0]
A = [ 2, 3, 7, 4 ]
output = [0, 0, 2, 3, 7, 4, 0, 0, 0] or [0, 0, 0, 2, 3, 7, 4, 0, 0] # Because there are two middle elements if N is even
A = [ 1, 3, 3, 4, 7, 6, 4, 3, 3, 2, 2, 2, 1 ] # N == 13, so remove 4 elements (2 at the right, 2 at the left) to make the output size 9
output = [3, 4, 7, 6, 4, 3, 3, 2, 2]
A = [ 1, 2, 3, 3, 4, 7, 6, 4, 3, 3, 2, 2, 2, 1 ]
output = [3, 3, 4, 7, 6, 4, 3, 3, 2] or [3, 4, 7, 6, 4, 3, 3, 2, 2]
Imagine you want an output list of n=9 with zeros padding and an input list A.
Then treat the thing as separate problems:
If len(A) == n return A
If len(A) > n then return the middle n elements of A.
Else return a list that starts with (n - len(A)) // 2 zeros, then A, then ends with n - (n - len(A)) // 2 - len(A) zeros (however much is left over from n elements).
E.g.
def fulllist(A, n):
if len(A) == n:
return A
if len(A) > n:
start = (len(A) - n) // 2
return A[start:start+n]
if len(A) < n:
leftpad = [0] * ((n - len(A)) // 2)
rightpad = [0] * (n - len(leftpad) - len(A))
return leftpad + A + rightpad
This gives the following as output:
>>> fulllist([2, 5, 1], 9)
[0, 0, 0, 2, 5, 1, 0, 0, 0]
>>> fulllist([2, 3, 7, 4], 9)
[0, 0, 2, 3, 7, 4, 0, 0, 0]
>>> fulllist([1, 3, 3, 4, 7, 6, 4, 3, 3, 2, 2, 2, 1], 9)
[3, 4, 7, 6, 4, 3, 3, 2, 2]
>>> fulllist([1, 2, 3, 3, 4, 7, 6, 4, 3, 3, 2, 2, 2, 1], 9)
[3, 3, 4, 7, 6, 4, 3, 3, 2]
The above function was written to match the pseudocode, but it would be better to alter it slightly, eliminating case 1. by treating it as a special case of 2. or 3.. That way the code is shorter, and more important, the function always returns a brand new list in every case instead of sometimes returning a reference to the input list, which could get confused in subsequent code and lead to some bugs. I chose to merge 1. with 2.
def fulllist(A, n):
if len(A) >= n:
start = (len(A) - n) // 2
return A[start:start+n]
else:
leftpad = [0] * ((n - len(A)) // 2)
rightpad = [0] * (n - len(leftpad) - len(A))
return leftpad + A + rightpad
Or you can shorten the code further by abusing the fact that [0] * -1 == [].
def fulllist(A, n):
leftpad = [0] * ((n - len(A)) // 2)
rightpad = [0] * (n - len(leftpad) - len(A))
start = (len(A) - n) // 2 if len(A) > n else 0
contents = A[start:start+n]
return leftpad + contents + rightpad
Although that may be going too far for some and it might make the code harder to understand. I like it though.
you can try something like this:
def padding(arr,n):
diff = abs(n - len(arr))
start, end = int(diff / 2), diff - int(diff / 2)
if len(arr) < n:
for i in range(start):
arr.insert(0,0)
for i in range(end):
arr.append(0)
else:
for i in range(start):
arr.pop(0)
for i in range(end):
arr.pop(-1)
return arr
A = [ 1, 3, 3, 4, 7, 6, 4, 3, 3, 2, 2, 2, 1 ]
print(padding(A,9))
Try -
def padding(l1):
flag = 0
while len(l1)>=9:
if len(l1) == 9:
return l1
if flag %2== 0:
l1.pop()
else:
l1.pop(0)
flag+=1
if len(l1)<9:
iterations = (9- len(l1))//2
for _ in range(iterations):
l1.insert(0,0)
l1.append(0)
if iterations % 2 == 0:
l1.append(0)
return l1
padding(A)

Replace values in a list if condition is true

how can I replace the numbers that are greater than 9 by their sum of digits?
right now the list multipliedlist =
[1, 4, 3, 8, 5, 12, 7, 16, 2]
I need to change it to (ex, num 12 and num 16 replaced to (3) and (7) )
[1, 4, 3, 8, 5, 3, 7, 7, 2]
I can use sum(map(int, str(number))) to add the digits but how can i change the values in the same list by their index?
def check_id_valid(id_number):
updatedid = map(int, str(id_number))
multipliedlist = [i * 1 if j % 2 == 0 else i * 2 for j, i in enumerate(updatedid)]
# for index, number in enumerate(multipliedlist):
# if multipliedlist[index] > 9:
# multipliedlist[index] = sum(map(int, str(number)))
# else:
# multipliedlist[index] == number #statement has no effect error.
print(check_id_valid(123456782))
New to python sorry if this is not explained as it's supposed to be
I appreciate any help,Thanks :)
Using a list comprehension
Ex:
data = [1, 4, 3, 8, 5, 12, 7, 16, 2]
print([sum(map(int, str(i))) if i > 9 else i for i in data])
Output:
[1, 4, 3, 8, 5, 3, 7, 7, 2]
Break your task into the constituent parts, namely
replacing a number with the sum of its digits
doing that for a list of numbers.
def sum_digits(number):
# Convert the number into a string (10 -> "10"),
# iterate over its characters to convert each of them
# back to an integer, then use the `sum()` builtin for
# summing.
return sum(int(digit_char) for digit_char in str(number))
def sum_all_digits(numbers):
return [sum_digits(number) for number in numbers]
print(sum_all_digits([1, 4, 3, 8, 5, 12, 7, 16, 2]))
outputs the expected
[1, 4, 3, 8, 5, 3, 7, 7, 2]
To change values by index you can use enumerate() function:
def sum_digits(n):
r = 0
while n:
r, n = r + n % 10, n // 10
return r
multipliedlist = [1, 4, 3, 8, 5, 12, 7, 16, 2]
for i, n in enumerate(multipliedlist):
multipliedlist[i] = sum_digits(multipliedlist[i])
print(multipliedlist)
[1, 4, 3, 8, 5, 3, 7, 7, 2]

How to generate all the combinations of the elements from an array in order?

I want to get all the combinations of an array's element in the following order.
say: a = [2, 3, 5], then after I call mysterious(a), I should get another array that is: [2, 3, 5, 2 * 3, 2 * 5, 3 * 5, 2 * 3 * 5] or [2, 3, 5, 6, 10, 15, 30]. Note: must be directly in this order.
To make my question more clear:
when lst = [2, 3, 5, 7], the return lst should be [2, 3, 5, 7, 2 * 3, 2 * 5, 2 * 7, 3 * 5, 3 * 7, 5 * 7, 2 * 3 * 5, 2 * 3 * 7, 2 * 5 * 7, 3 * 5 * 7, 2 * 3 * 5 * 7] or [2, 3, 5, 7, 6, 10, 14, 15, 21, 35, 30, 42, 70, 105, 210]
you can think of the returnList is in the order of (nCr n chooses r) nC1, nC2, ..., nCn.
I am asking for a generic answer, you should handle arbitrary length of input list.
I can apply a recursion algorithm to derive all the combinations, but due to how recursion works, I can only get [2, 3, 2 * 3, 5, 2 * 5, 3 * 5, 2 * 3 * 5] or [2, 3, 6, 5, 10, 15, 30], which is in a wrong order.
See my code below:
def listBuilding(lst):
length = len(lst)
if len(lst) == 2:
return [lst[0], lst[1], lst[0] * lst[1]]
else:
previous = listBuilding(lst[:(length - 1)])
return previous + [lst[length - 1]] + [(lst[length - 1] * x) for x in previous]
Can someone help me? I think this should be a common problem, and someone might have answered this before, but I cannot find it.
I am expecting an easy answer.
You might need to use functools.reduce and itertools.combinations and operator.mul with a nested for loop which does it, also add a and l at the end:
>>> from functools import reduce
>>> from itertools import combinations
>>> import operator
>>> a = [2, 3, 5]
>>> l = []
>>> for i in range(2, len(a) + 1):
for x in combinations(a, i):
l.append(reduce(operator.mul, x, 1))
>>> a + l
[2, 3, 5, 6, 10, 15, 30]
>>>

python: how to strip lines efficiently from a matrix, which have elements appearing in other lines

list = [0, 1, 2, 3, 4, 1, 5, 0, 6, 5, 7, 8, 9, 10, 11, 12, 13, 2]
list is used "matrix like"
1. 0 1 2
2. 3 4 1
3. 5 0 6
... and so on. I would like to write all those lines into a new list/matrix, but without lines, that would repeat a number. However the order of a line has to be preserved.
So far I use this:
compa = [0,1,2,3,4,1,5,0,6,5,7,8,9,10,11,12,13,2] #the list to be used as base
temp = [0,1,2] #new list starts from the first element
temp2 = [12,13,2] #new list starts from the last element
Mischzahl = 3 #defines the number of elements in a line of the "matrix"
n = 0
while n < len(compa):
for m in range(0,len(temp)):
if temp[m] == compa[n]:
n = (int(n/Mischzahl) + 1) * Mischzahl - 1 #calculates the "foul" line and sets n to the next line
break
if (n + 1) % Mischzahl == 0 and m == len(temp) - 1 : #if the end of temp is reached, the current line is transferred to temp.
for p in range(Mischzahl):
temp.append(compa[Mischzahl*int(n/Mischzahl) + p])
n += 1
and the same backwards
n = len(compa) - 1
while n > 0: #same as above but starting from last element
for m in range(len(temp2)):
if temp2[m] == compa[n]:
n = (int(n/Mischzahl) - 1) * Mischzahl + Mischzahl
break
if (n) % Mischzahl == 0 and m == len(temp2) - 1:
for p in range(Mischzahl):
temp2.append(compa[Mischzahl*int(n/Mischzahl) + p])
n = n - 1
resulting output for temp and temp2:
[0, 1, 2, 3, 4, 1, 5, 0, 6, 5, 7, 8, 9, 10, 11, 12, 13, 2] #compa
[0, 1, 2, 5, 7, 8, 9, 10, 11] #temp
[12, 13, 2, 9, 10, 11, 5, 7, 8, 3, 4, 1] #temp2
Since this is the most time-consuming part of the script: Is there a more efficient way to do this? Any helpful advice or direction would be highly welcome.
You can define a function that iterates over the list in strides of a given length (in your case 3), checks if the elements of the stride are in a set of numbers, if not extend the out list and update the set.
from math import ceil
def unique_by_row(compa, stride_size=3, reverse=False):
strides = ceil(len(compa)/stride_size)
out = []
check = set()
it = range(strides)
if reverse:
it = reversed(it)
for i in it:
x = compa[stride_size*i:stride_size*(i+1)]
if not check.intersection(x):
out.extend(x)
check.update(x)
return out
Tests:
compa = [0, 1, 2, 3, 4, 1, 5, 0, 6, 5, 7, 8, 9, 10, 11, 12, 13, 2]
unique_by_row(compa)
# returns:
[0, 1, 2, 5, 7, 8, 9, 10, 11]
unique_by_row(compa, reverse=True)
# returns:
[12, 13, 2, 9, 10, 11, 5, 7, 8, 3, 4, 1]

Algorithm to return a reordered range for data rendering

Here are examples:
given: 1,2,3 [list or range of numbers]
return: 2,1,3 [reordered list]
given: 1,2,3,4,5
return: 3 1 5 2 4
given: 1,2,3,4,5,6,7
return: 4 1 7 2 6 3 5 OR 4 7 1 5 3 2 6 or similar
given: 1,2,4,5,6,7,8,9
return: 5,1,9,3,7,2,8,4,6 or similar
In rendering you start with the center, then the most extreme cases, and become more and more detailed. This is NOT random. I'm in python, but theres got to be a name for this in comp sci. Help appreciated.
Edit to add
even case -
given: 1234
return: 2,1,4,3 OR 3,1,4,2 OR 2,4,1,3 OR 3,4,1,2
A valid, although ungraceful solution:
def sigorder(lst):
result = []
l = len(lst)
if l <= 2:
return lst
if l > 2:
result.append(lst[l/2])
result.append(lst[0])
result.append(lst[-1])
right = sigord(lst[l/2+1:-1])
left = sigord(lst[1:l/2])
result.extend(slicezip(left, right))
return result
Inner, recursive function:
def sigord(lst):
result = []
if len(lst) < 3:
return lst
else:
l = len(lst)
result.append(lst[l/2])
left = sigord(lst[0:l/2])
right = sigord(lst[l/2 + 1:len(lst)])
result.extend(slicezip(left, right))
return result
slicezip() (Note: conveniently handles the potential unevenness of the left/right lists automagically)
def slicezip(a, b):
result = [0]*(len(a)+len(b))
result[::2] = a
result[1::2] = b
return result
Outputs for lists length 4-9 :
[3, 1, 4, 2]
[3, 1, 5, 2, 4]
[4, 1, 6, 2, 5, 3]
[4, 1, 7, 2, 5, 3, 6]
[5, 1, 8, 3, 6, 2, 7, 4]
[5, 1, 9, 3, 7, 2, 6, 4, 8]
This should do it:
def extreme_cases(upd_itrr, new_itrr):
new_itrr.append(min(upd_itrr))
new_itrr.append(max(upd_itrr))
upd_itrr.remove(min(upd_itrr))
upd_itrr.remove(max(upd_itrr))
if len(upd_itrr) >= 2:
extreme_cases(upd_itrr, new_itrr)
return upd_itrr, new_itrr
def reordered_range(itr):
new_itr = []
center = 0
if len(itr) % 2 != 0:
center = itr[len(itr) // 2]
elif len(itr) % 2 == 0:
center = itr[(len(itr) // 2) - 1]
new_itr.append(center)
upd_itr = itr[:]
upd_itr.remove(center)
upd_itr, new_itr = extreme_cases(upd_itr, new_itr)
if upd_itr:
new_itr.append(upd_itr[0])
return new_itr
print(reordered_range([1, 2, 3]))
print(reordered_range([1, 2, 3, 4]))
print(reordered_range([1, 2, 3, 4, 5]))
print(reordered_range([1, 2, 3, 4, 5, 6, 7]))
print(reordered_range([1, 2, 4, 5, 6, 7, 8, 9]))
Output:
[2, 1, 3]
[2, 1, 4, 3]
[3, 1, 5, 2, 4]
[4, 1, 7, 2, 6, 3, 5]
[5, 1, 9, 2, 8, 4, 7, 6]
Another solution:
import numpy as np
from copy import copy
def bisecting_order(lst):
# bisecting order of an unordered list
result = []
l = len(lst)
if l < 3:
return lst
result.append(closest(lst,np.mean(lst)))
result.append(min(lst))
result.append(max(lst))
# get bisections
while len(result)!=len(lst):
temp_list = copy(result)
temp_list.sort()
for i in xrange(len(temp_list)-1):
newnum = closest(lst,np.mean([temp_list[i],temp_list[i+1]]))
if newnum in result:
continue
else:
result.append(newnum)
return result
def closest(mylist,mynum):
return min(mylist, key=lambda x:abs(x-mynum))

Categories