Question
You have L, a list containing some digits (0 to 9). Write a function solution(L) which finds the largest number that can be made from some or all of these digits and is divisible by 3.
If it is not possible to make such a number, return 0 as the solution. L will contain anywhere from 1 to 9 digits. The same digit may appear multiple times in the list, but each element in the list may only be used once.
Test Cases
Input:
solution.solution([3, 1, 4, 1])
Output:
4311
Input:
solution.solution([3, 1, 4, 1, 5, 9])
Output:
94311
My code
def sum(L):
totalSum = 0
for x in range(len(L)):
totalSum = totalSum + L[x]
return totalSum
def listToInteger(L):
strings = [str(integer) for integer in L ]
concatString = "".join(strings)
finalInt = int(concatString)
return finalInt
def solution(L):
num = sum(L)
if not num % 3:
L.sort(reverse=True) # sort list in descending order to create largest number
return listToInteger(L)
else:
n = num % 3
flag = False
while not flag: # locate digit causing indivisiblity
if n in L:
L.remove(n)
L.sort(reverse=True)
return listToInteger(L)
elif(n > num):
return 0
else:
n += 3
I get the two test cases correct, but there is one hidden case that keeps failing. I'm not sure if the input is not strict enough, or if there is a fault in my logic
the only fault in logic I can think of is if the input was [8,5,3] , the sum would be 16 and 16 % 3 = 1
so it would check the list for 1, 4, 7, 10, 13 , 16 but it wouldnt be in the list so it wouldn't remove 8 or 5. it would return 0 when it should actually return [3].
I added a function for this but even then it was still failing the hidden test case. . .
Any suggestions would be appreciated
Your code seems to assume that there can only be one digit that is wrong. What would you do with input like 1,1,3? sum is 5, n is 2 and you'll try to remove 2, 5, and then fail and return 0.
You need to change your assumptions and check other digits too, and make it possible to remove more than 1 digit when working toward a solution.
This code worked fine for [8,5,3]
example: [8,5,3,6]
sum will be 22
sum%3 will be 1
so numbers need to check in list to delet are 1,4 7,10,13,16,19,22 and it will never delet any elements,since there are no these elements in the list
so still there are 6 and 3 which can be multilple of 3.
so take 3 and 6 in a list and sort them and answer will be 63
def sum(L):
totalSum = 0
for x in range(len(L)):
totalSum = totalSum + L[x]
return totalSum
def listToInteger(L):
strings = [str(integer) for integer in L ]
concatString = "".join(strings)
finalInt = int(concatString)
return finalInt
def solution(L):
num = sum(L)
if not num % 3:
L.sort(reverse=True) # sort list in descending order to create largest number
return listToInteger(L)
else:
n = num % 3
flag = False
while not flag: # locate digit causing indivisiblity
if n in L:
L.remove(n)
L.sort(reverse=True)
return listToInteger(L)
elif(n > num):
k=[]
for i in L:
if i%3==0:
k.append(i)
if len(k)!=0:
k.sort(reverse=True)
return listToInteger(k)
else:
return 0
else:
n += 3
l=[8,5,3]
print(solution(l))
Related
Is there a pythonic way to find out which number is different in evenness from others ?
E.g.:
input: "2 4 7 8 10" => output: 3 // Third number is odd, while the rest of the numbers are even
input: "1 2 1 1" => 2 // Second number is even, while the rest of the numbers are odd
Bellow is my approach, where numbers is the input as str:
def evenness(numbers):
bool_number = list(map(lambda i: i%2==0, map(lambda i: int(i), numbers.split(" "))))
if bool_number.count(True) == 1:
return bool_number.index(True)+1
else:
return bool_number.index(False)+1
Thanks
If you only ever have one instance of an odd/even discrepancy, you can convert all numbers to 1s (for odds) and 0s (for evens) and check for the first 1 or first 0 depending on whether you have more than one odd:
s = "2 4 7 8 10"
odds = [int(n)&1 for n in s.split()]
index = odds.index(sum(odds)==1)+1
print(index) # 3
You can try this function it will return you the index of the only item that is different then the others and if there will be more then one or zero occurrence then it will return -1
def evenness(numbers):
res = list(filter(lambda x: x.count(0) == len(x) -1, [[i if int(n) % 2 else 0 for i, n in enumerate(numbers.split(" "))], [i if not int(n) % 2 else 0 for i, n in enumerate(numbers.split(" "))]]))
return -1 if len(res) != 1 else sum(res[0])
def summer_69(arr):
for i in range(0,len(arr)-1):
if arr[i] == range (6,10):
del arr[i]
elif arr[i] != range(6,10):
return arr[i] + arr[i + 1]
print(summer_69([1,3,5]))
When I print it out it prints 4 for some reason instead of 9? I am a beginner so sorry if my code is slobby. Basicially the problem is asking for us to give them the sum but ignore the numbers 6 through 9. Can someone please tell me what im doing wrong and is there like an easier way to do this?
You're not skipping the section of numbers starting with 6 and ending with 9, you're just skipping any numbers between 6 and 9.
You can use a flag variable to indicate when you're in this section.
You're also not summing all the numbers. You're returning as soon as you find a number that's not in the range, and just adding that number and the next number.
def summer_69(arr):
in_69 = False
total = 0
for num in arr:
if in_69:
if num == 9:
in_69 = False
elif num == 6:
in_69 = True
else:
total += num
return total
You can use functional programming. array object has map() and reduce() methods
var a = [1, 3,5];
var r = a.filter((e)=>e < 6 ||e > 9).reduce((prev, e) => prev + e);
console.log(r);
a.filter((e)=>e < 6 ||e > 9)) this filters the numbers that are not in the range (6, 9) and return an array of numbers that are not in the range(6,9)
.reduce((prev, e) => prev + e) this will iteratively adds each number and return a single value.
cleaner solution using a set for lookup:
def s69(arr):
if len(arr) == 0:
return 0
out = 0
d = {6,7,8,9}
for a in arr:
if a not in d:
out+=a
return out
I was working on a problem that determines whether the digits in the numbers are in the increasing sequence. Now, the approach I took to solve the problem was, For instance, consider the number 5678.
To check whether 5678 is an increasing sequence, I took the first digit and the next digit and the last digit which is 5,6,8 and substitute in range function range(first,last,(diff of first digit and the next to first digit)) i.e range(5,8+1,abs(5-6)).The result is the list of digits in the ascending order
To this problem, there is a constraint saying
For incrementing sequences, 0 should come after 9, and not before 1, as in 7890. Now my program breaks at the input 7890. I don't know how to encode this logic. Can someone help me, please?.
The code for increasing sequence was
len(set(['5','6','7','8']) - set(map(str,range(5,8+1,abs(5-6))))) == 0
You can simply check if the number, when converted to a string, is a substring of '1234567890':
str(num) in '1234567890'
you could zip the string representation of the number with a shifted self and iterate on consecutive digits together. Use all to check that numbers follow, using a modulo 10 to handle the 0 case.
num = 7890
result = all((int(y)-int(x))%10 == 1 for x,y in zip(str(num),str(num)[1:]))
I would create a cycling generator and slice that:
from itertools import cycle, islice
num = 5678901234
num = tuple(str(num))
print(num == tuple(islice(cycle(map(str, range(10))), int(num[0]), int(num[0]) + len(num))))
This is faster than solutions that check differences between individual digits. Of course, you can sacrifice the length to make it faster:
def digits(num):
while num:
yield num % 10
num //= 10
def check(num):
num = list(digits(num))
num.reverse()
for i, j in zip(islice(cycle(range(10)), num[0], num[0] + len(num)), num):
if i != j:
return False
return True
Since you already have the zip version, here is an alternative solution:
import sys
order = dict(enumerate(range(10)))
order[0] = 10
def increasing(n):
n = abs(n)
o = order[n % 10] + 1
while n:
n, r = divmod(n, 10)
if o - order[r] != 1:
return False
o = order[r]
return True
for n in sys.argv[1:]:
print n, increasing(int(n))
Here's my take that just looks at the digits and exits as soon as there is a discrepancy:
def f(n):
while (n):
last = n % 10
n = n / 10
if n == 0:
return True
prev = n % 10
print last, prev
if prev == 0 or prev != (last - 1) % 10:
return False
print f(1234)
print f(7890)
print f(78901)
print f(1345)
Somehow this question got me thinking of Palindromes and that got me to thinking of this in a different way.
5 6 7 8
8 7 6 5
-------------
13 13 13 13
9 0 1
1 0 9
---------
10 0 10
9 0 1 2
2 1 0 9
-------------
11 1 1 11
And that leads to this solution and tests.
pos_test_data = [5678, 901, 9012, 9012345678901]
neg_test_data = [5876, 910, 9021]
def monotonic_by_one(n):
fwd = str(n)
tgt = ord(fwd[0]) + ord(fwd[-1])
return all([ord(f) + ord(r) in (tgt, tgt - 10) for f, r in zip(fwd, reversed(fwd))])
print("Positive: ", all([monotonic_by_one(n) for n in pos_test_data]))
print("Negative: ", all([not monotonic_by_one(n) for n in neg_test_data]))
Results:
Positive: True
Negative: True
Instead of using to full list comprehension you could use a for loop and bail out at the first failure. I'd want to look at the size of the numbers being checked and time somethings to decide which was faster.
I would try this, a little verbose for readability:
seq = list(input())
seq1 = seq[1:]
seq2 = seq[:-1]
diff = [x-y for x,y in zip([int(x) if int(x)>0 else 10 for x in seq1],[int(x) if int(x)>0 else 10 for x in seq2])]
if any (t != 1 for t in diff) :
print('not <<<<<')
else :
print('<<<<<<')
A simple solution that checks the next number in the sequence and then using current_number + 1 == next_number to detect sequence.
import bisect
def find_next(x, a):
i = bisect.bisect_right(x, a)
if i:
return x[i]
return None
def is_sequence(x):
ans = True
for i in x[:-1]:
next_num = find_next(x, i)
if next_num and i+1 != next_num:
ans = False
break
return ans
print(is_sequence([1,2,3,4])) # True
Google Foobar Question:
Please Pass the Coded Messages
You need to pass a message to the bunny prisoners, but to avoid detection, the code you agreed to use is... obscure, to say the least. The bunnies are given food on standard-issue prison plates that are stamped with the numbers 0-9 for easier sorting, and you need to combine sets of plates to create the numbers in the code. The signal that a number is part of the code is that it is divisible by 3. You can do smaller numbers like 15 and 45 easily, but bigger numbers like 144 and 414 are a little trickier. Write a program to help yourself quickly create large numbers for use in the code, given a limited number of plates to work with.
You have L, a list containing some digits (0 to 9). Write a function answer(L) which finds the largest number that can be made from some or all of these digits and is divisible by 3. If it is not possible to make such a number, return 0 as the answer. L will contain anywhere from 1 to 9 digits. The same digit may appear multiple times in the list, but each element in the list may only be used once.
Languages
To provide a Python solution, edit solution.py
To provide a Java solution, edit solution.java
Test cases
Inputs:
(int list) l = [3, 1, 4, 1]
Output:
(int) 4311
Inputs:
(int list) l = [3, 1, 4, 1, 5, 9]
Output:
(int) 94311
Use verify [file] to test your solution and see how it does. When you are finished editing your code, use submit [file] to submit your answer. If your solution passes the test cases, it will be removed from your home folder.
So that's the question, my python code only passes 3 out of 5 tests cases. I spent a few hours but can't find out what cases I am missing. Here is my code:
maximum = [0, 0, 0, 0, 0,0,0,0,0]
def subset_sum(numbers, target, partial=[]):
global maximum
s = sum(partial)
if s%3 == 0:
if s != 0:
str1 = ''.join(str(e) for e in partial)
y = int(str1)
str1 = ''.join(str(e) for e in maximum)
z = int(str1)
if y>z:
maximum = partial
# print maximum
if s >= target:
return # if we reach the number why bother to continue
for i in range(len(numbers)):
n = numbers[i]
remaining = numbers[i+1:]
subset_sum(remaining, target, partial + [n])
def answer(l):
global maximum
#maximum = [0, 0, 0, 0, 0]
subset_sum(l,sum(l))
maximum = sorted(maximum, key=int, reverse=True)
str1 = ''.join(str(e) for e in maximum)
y = int(str1)
return y
print(answer([3,1,4,1,5,9]))
So what test cases am I not accounting for, and how could I improve it?
try this using combination it may help:
from itertools import combinations
def answer(nums):
nums.sort(reverse = True)
for i in reversed(range(1, len(nums) + 1)):
for tup in combinations(nums, i):
if sum(tup) % 3 == 0: return int(''.join(map(str, tup)))
return 0
Presently, you are forming a number by using adjacent digits only while the question does not say so.
A quick fix would be to set remaining list properly -
remaining = numbers[:i] + numbers[i+1:]
But you need to think of better algorithm.
Update
inputNumbers = [2, 1, 1, 1, 7, 8, 5, 7, 9, 3]
inputNumSorted = sorted(inputNumbers)
sumMax = sum(inputNumbers)
queue = [(sumMax, inputNumSorted)]
found = False
while (len(queue) > 0):
(sumCurrent, digitList) = queue.pop()
remainder = sumCurrent%3
if (remainder == 0):
found = True
break
else :
for index, aNum in enumerate(digitList):
if(aNum%3 == remainder):
sumCurrent -= remainder
digitList.remove(aNum)
found = True
break
else:
newList = digitList[:index]+digitList[index+1:]
if (len(newList) > 0):
queue.insert(0, (sumCurrent-aNum, newList))
if(found):
break
maxNum = 0
if (found):
for x,y in enumerate(digitList):
maxNum += (10**x)*y
print(maxNum)
I believe the solution looks something like this:
Arrange the input digits into a single number, in order from largest to smallest. (The specific digit order won't affect its divisibility by 3.)
If this number is divisible by 3, you're done.
Otherwise, try removing the smallest digit. If this results in a number that is divisible by 3, you're done. Otherwise start over with the original number and try removing the second-smallest digit. Repeat.
Otherwise, try removing digits two at a time, starting with the two smallest. If any of these result in a number that is divisible by 3, you're done.
Otherwise, try removing three digits...
Four digits...
Etc.
If nothing worked, return zero.
Here's the actual solution and this passes in all the test cases
import itertools
def solution(l):
l.sort(reverse = True)
for i in reversed(range(1, len(l) + 1)):
for j in itertools.combinations(l, i):
if sum(tup) % 3 == 0: return int(''.join(map(str, j)))
return 0
Here is a commented solution (that passed all test cases):
def solution(l):
# sort in decending order
l = sorted(l, reverse = True)
# if the number is already divisible by three
if sum(l) % 3 == 0:
# return the number
return int("".join(str(n) for n in l))
possibilities = [0]
# try every combination of removing a single digit
for i in range(len(l)):
# copy list of digits
_temp = l[:]
# remove a digit
del _temp[len(_temp) - i - 1]
# check if it is divisible by three
if sum(_temp) % 3 == 0:
# if so, this is our solution (the digits are removed in order)
return int("".join(str(n) for n in _temp))
# try every combination of removing a second digit
for j in range(1, len(_temp)):
# copy list of digits again
_temp2 = _temp[:]
# remove another digit
del _temp2[len(_temp2) - j - 1]
# check if this combination is divisible by three
if sum(_temp2) % 3 == 0:
# if so, append it to the list of possibilities
possibilities.append(int("".join(str(n) for n in _temp2)))
# return the largest solution
return max(possibilities)
I tried a lot but test case 3 fails .Sorry for bad variable names
import itertools
def solution(l):
a=[]
k=''
aa=0
b=[]
for i in range(len(l)+1):
for j in itertools.combinations(l,i):
a.append(j)
for i in a:
if sum(i)>=aa and sum(i)%3==0 and len(b)<len(i):
aa=sum(i)
b=i[::-1]
else:
pass
b=sorted(b)[::-1]
for i in b:
k+=str(i)
if list(k)==[]:
return 0
else:
return k
For example:
input: A = [ 6 4 3 -5 0 2 -7 1 ]
output: 5
Since 5 is the smallest positive integer that does not occur in the array.
I have written two solutions to that problem. The first one is good but I don't want to use any external libraries + its O(n)*log(n) complexity. The second solution "In which I need your help to optimize it" gives an error when the input is chaotic sequences length=10005 (with minus).
Solution 1:
from itertools import count, filterfalse
def minpositive(a):
return(next(filterfalse(set(a).__contains__, count(1))))
Solution 2:
def minpositive(a):
count = 0
b = list(set([i for i in a if i>0]))
if min(b, default = 0) > 1 or min(b, default = 0) == 0 :
min_val = 1
else:
min_val = min([b[i-1]+1 for i, x in enumerate(b) if x - b[i - 1] >1], default=b[-1]+1)
return min_val
Note: This was a demo test in codility, solution 1 got 100% and
solution 2 got 77 %.
Error in "solution2" was due to:
Performance tests ->
medium chaotic sequences length=10005 (with minus) got 3 expected
10000
Performance tests -> large chaotic + many -1, 1, 2, 3 (with
minus) got 5 expected 10000
Testing for the presence of a number in a set is fast in Python so you could try something like this:
def minpositive(a):
A = set(a)
ans = 1
while ans in A:
ans += 1
return ans
Fast for large arrays.
def minpositive(arr):
if 1 not in arr: # protection from error if ( max(arr) < 0 )
return 1
else:
maxArr = max(arr) # find max element in 'arr'
c1 = set(range(2, maxArr+2)) # create array from 2 to max
c2 = c1 - set(arr) # find all positive elements outside the array
return min(c2)
I have an easy solution. No need to sort.
def solution(A):
s = set(A)
m = max(A) + 2
for N in range(1, m):
if N not in s:
return N
return 1
Note: It is 100% total score (Correctness & Performance)
def minpositive(A):
"""Given an list A of N integers,
returns the smallest positive integer (greater than 0)
that does not occur in A in O(n) time complexity
Args:
A: list of integers
Returns:
integer: smallest positive integer
e.g:
A = [1,2,3]
smallest_positive_int = 4
"""
len_nrs_list = len(A)
N = set(range(1, len_nrs_list+2))
return min(N-set(A)) #gets the min value using the N integers
This solution passes the performance test with a score of 100%
def solution(A):
n = sorted(i for i in set(A) if i > 0) # Remove duplicates and negative numbers
if not n:
return 1
ln = len(n)
for i in range(1, ln + 1):
if i != n[i - 1]:
return i
return ln + 1
def solution(A):
B = set(sorted(A))
m = 1
for x in B:
if x == m:
m+=1
return m
Continuing on from Niroj Shrestha and najeeb-jebreel, added an initial portion to avoid iteration in case of a complete set. Especially important if the array is very large.
def smallest_positive_int(A):
sorted_A = sorted(A)
last_in_sorted_A = sorted_A[-1]
#check if straight continuous list
if len(sorted_A) == last_in_sorted_A:
return last_in_sorted_A + 1
else:
#incomplete list, iterate to find the smallest missing number
sol=1
for x in sorted_A:
if x == sol:
sol += 1
else:
break
return sol
A = [1,2,7,4,5,6]
print(smallest_positive_int(A))
This question doesn't really need another answer, but there is a solution that has not been proposed yet, that I believe to be faster than what's been presented so far.
As others have pointed out, we know the answer lies in the range [1, len(A)+1], inclusively. We can turn that into a set and take the minimum element in the set difference with A. That's a good O(N) solution since set operations are O(1).
However, we don't need to use a Python set to store [1, len(A)+1], because we're starting with a dense set. We can use an array instead, which will replace set hashing by list indexing and give us another O(N) solution with a lower constant.
def minpositive(a):
# the "set" of possible answer - values_found[i-1] will tell us whether i is in a
values_found = [False] * (len(a)+1)
# note any values in a in the range [1, len(a)+1] as found
for i in a:
if i > 0 and i <= len(a)+1:
values_found[i-1] = True
# extract the smallest value not found
for i, found in enumerate(values_found):
if not found:
return i+1
We know the final for loop always finds a value that was not marked, because it has one more element than a, so at least one of its cells was not set to True.
def check_min(a):
x= max(a)
if x-1 in a:
return x+1
elif x <= 0:
return 1
else:
return x-1
Correct me if i'm wrong but this works for me.
def solution(A):
clone = 1
A.sort()
for itr in range(max(A) + 2):
if itr not in A and itr >= 1:
clone = itr
break
return clone
print(solution([2,1,4,7]))
#returns 3
def solution(A):
n = 1
for i in A:
if n in A:
n = n+1
else:
return n
return n
def not_in_A(a):
a=sorted(a)
if max(a)<1:
return(1)
for i in range(0,len(a)-1):
if a[i+1]-a[i]>1:
out=a[i]+1
if out==0 or out<1:
continue
return(out)
return(max(a)+1)
mark and then find the first one that didn't find
nums = [ 6, 4, 3, -5, 0, 2, -7, 1 ]
def check_min(nums):
marks = [-1] * len(nums)
for idx, num in enumerate(nums):
if num >= 0:
marks[num] = idx
for idx, mark in enumerate(marks):
if mark == -1:
return idx
return idx + 1
I just modified the answer by #najeeb-jebreel and now the function gives an optimal solution.
def solution(A):
sorted_set = set(sorted(A))
sol = 1
for x in sorted_set:
if x == sol:
sol += 1
else:
break
return sol
I reduced the length of set before comparing
a=[1,222,3,4,24,5,6,7,8,9,10,15,2,3,3,11,-1]
#a=[1,2,3,6,3]
def sol(a_array):
a_set=set()
b_set=set()
cnt=1
for i in a_array:
#In order to get the greater performance
#Checking if element is greater than length+1
#then it can't be output( our result in solution)
if i<=len(a) and i >=1:
a_set.add(i) # Adding array element in set
b_set.add(cnt) # Adding iterator in set
cnt=cnt+1
b_set=b_set.difference(a_set)
if((len(b_set)) > 1):
return(min(b_set))
else:
return max(a_set)+1
sol(a)
def solution(A):
nw_A = sorted(set(A))
if all(i < 0 for i in nw_A):
return 1
else:
ans = 1
while ans in nw_A:
ans += 1
if ans not in nw_A:
return ans
For better performance if there is a possibility to import numpy package.
def solution(A):
import numpy as np
nw_A = np.unique(np.array(A))
if np.all((nw_A < 0)):
return 1
else:
ans = 1
while ans in nw_A:
ans += 1
if ans not in nw_A:
return ans
def solution(A):
# write your code in Python 3.6
min_num = float("inf")
set_A = set(A)
# finding the smallest number
for num in set_A:
if num < min_num:
min_num = num
# print(min_num)
#if negative make positive
if min_num < 0 or min_num == 0:
min_num = 1
# print(min_num)
# if in set add 1 until not
while min_num in set_A:
min_num += 1
return min_num
Not sure why this is not 100% in correctness. It is 100% performance
def solution(A):
arr = set(A)
N = set(range(1, 100001))
while N in arr:
N += 1
return min(N - arr)
solution([1, 2, 6, 4])
#returns 3