Binary strings recursive function - python

How to write a recursive function that generates a list of binary of length n with a specified number of 1s?
Here's a code that generates recursively a list of binarys; without a specified number of 1s:
def generateAllBinaryStrings(n, arr, i):
if i == n:
printTheArray(arr, n)
return
# First assign "0" at ith position
# and try for all other permutations
# for remaining positions
arr[i] = 0
generateAllBinaryStrings(n, arr, i + 1)
# And then assign "1" at ith position
# and try for all other permutations
# for remaining positions
arr[i] = 1
generateAllBinaryStrings(n, arr, i + 1)
Taken from geeksforgeeks

You could do it like this:
def binaryStrings(n, ones):
if n < ones: # impossible
return []
if n == ones:
return ["1" * ones]
if ones == 0:
return ["0" * n]
a = binaryStrings(n-1, ones)
b = binaryStrings(n-1, ones-1)
return ["0"+s for s in a] + ["1"+s for s in b]
Example call to get all 6-digit binary numbers which have exactly 4 1-digits:
print(binaryStrings(6,4))

You have to generate all possible sequences with adding a 0 or a 1 at each position. Total possible sequences = 2^MAX. Keep track of the number of 1s in the current sequence so far to break.
# Generate all binary numbers with exactly "n" 1s
# Max digits in the binary number = MAX
def binary(n):
MAX = 5
all_solutions = []
def solve(current, remaining_ones):
if len(current) > MAX:
return
if remaining_ones == 0:
all_solutions.append(current+"0"*(MAX-len(current)))
return
solve(current+"1", remaining_ones - 1)
solve(current+"0", remaining_ones)
solve("", n)
return all_solutions
print(binary(2))
# ['11000', '10100', '10010', '10001', '01100', '01010', '01001', '00110', '00101', '00011']

Related

Print all n-digit numbers whose product of digits equals to given product python

enter image description hereDisplay 3-digit prime numbers that have the product of digits equal to a given p-value.
Example: For p = 9 the numbers 191, 313, 331, 911 meet the conditions of the problem.
I found a code that does this just to find out their amount but not the product.
I need to find out what I change in the program to find out the product, not the amount.
Here is the code to be solved in python:
def findNDigitNumsUtil(n, product, out,index):
# Base case
if (index > n or product < 0):
return
f = ""
# If number becomes N-digit
if (index == n):
# if sum of its digits is equal
# to given sum, print it
if(product == 0):
out[index] = "\0"
for i in out:
f = f + i
print(f, end = " ")
return
# Traverse through every digit. Note
# that here we're considering leading
# 0's as digits
for i in range(10):
# append current digit to number
out[index] = chr(i + ord('0'))
# recurse for next digit with reduced sum
findNDigitNumsUtil(n, product - i,
out, index + 1)
# This is mainly a wrapper over findNDigitNumsUtil.
# It explicitly handles leading digit
def findNDigitNums( n, sum):
# output array to store N-digit numbers
out = [False] * (n + 1)
# fill 1st position by every digit
# from 1 to 9 and calls findNDigitNumsUtil()
# for remaining positions
for i in range(1, 10):
out[0] = chr(i + ord('0'))
findNDigitNumsUtil(n, sum - i, out, 1)
# Driver Code
if __name__ == "__main__":
n = 3
sum = 9
findNDigitNums(n, sum)
# This code is contributed
# by ChitraNayal
Disclaimer: this code was written by Github Copilot with minimal supervision.
# Display 3-digit prime numbers that have the product of digits equal to a given p-value.
# Example: For p = 9 the numbers 191, 313, 331, 911 meet the conditions of the problem.
def is_prime(n):
if n == 1:
return False
for i in range(2, int(n**0.5)+1):
if n % i == 0:
return False
return True
def print_3_digit_primes(p):
for i in range(100, 1000):
if is_prime(i) and (i % 10) * (i // 100) * (i % 100 // 10) == p:
print(i)
print_3_digit_primes(9)

Finding how many times a certain character appears in a multiplied string

We want to find the number of 'a's in a given string s multiplied infinite times.
We will be given a number n that is the slicing size of the infinite string.
sample input:
aba 10
output:
7
Here aba is multiplied with 10, resulting in 'abaabaabaa'
and the no. of 'a's are 7.
This is my code:
def repeatedString(s, n):
count = 0
inters = s * n
reals = s[0:n+1]
for i in reals:
if (i == 'a'):
count += 1
return count
I'm getting 2 instead of 7 as the output (test case 'aba' 10). Where did I go wrong? I just multiplied the given string with n because it will never be greater than the slicing size.
Here's the link to the problem:
https://www.hackerrank.com/challenges/repeated-string/problem
Much simpler solution using python3.
s = input().strip()
n = int(input())
print(s[:n%len(s)].count('a')+(s.count('a')*(n//len(s))))
There's no reason to slice the string
def repeatedString(s, n):
count = 0
for index, i in enumerate(s*n):
if index >= n:
return count
if(i == 'a'):
count += 1
# empty string
return count
I used a simple unitary method.
Number of 'a' in one repetition is cnt_a so the number of 'a' in first n characters will be (cnt_a/len(s)) * n
def repeatedString(s, n):
if len(s)==1 and s=='a':
return n
cnt_a=0
for i in s:
if i == 'a':
cnt_a+=1
if cnt_a % 2 == 0:
no_a = (cnt_a/len(s)) * n
return math.ceil(no_a)
else:
no_a = (cnt_a/len(s)) * n
return math.floor(no_a)
If you would like a more readable answer....
def repeatedString(s, n):
target = 'a'
target_count = 0
# how many times does the string need to be repeated: (n // len(s) * s) + s[:(n % len(s))]
quotient = n // len(s)
remainder = n % len(s)
for char in s: # how many times target appears in 1 instance of the substring
if char == target:
target_count += 1
# how many times the target appears in many instances of the substring provided
target_count = target_count * quotient
for char in s[:remainder]: # count the remaining targets in the truncated substring
if char == target:
target_count += 1
return target_count
One liner answer:
return [s[i%len(s)] for i in range(n)].count('a')
There is only two problem in your code
s = 'aba'
n = 10
count = 0
inters = s * n
# Here you need to slice(inters) not (s) because s only hold 'aba'
# And not n+1 it's take 11 values only n
reals = inters[0:n]
for i in reals:
if (i == 'a'):
count += 1
print(count)
so if the string contains "a"s only simply return n. otherwise, count the number of a's in the string s, now using divmond() function I have found the number of string that can be added without surpassing n. for example string s is "aba" and n=10, so I can add 3 "abs"s completely without the length of string going over 10. now the number of a's in the added string (3*2). Now the places left to be filled are equal to the remainder(y) of divmond() function. Now slice the string s up to y and find the number of a's in it and add it to count.
divmond(10,3) returns (10//3) and it's remainder.
def repeatedString(s, n):
if len(s)==1 and s=="a":
return n
count=s.count("a")
x,y=divmod(n,len(s))
count=count*x
str=s[:y]
return count+str.count("a")
The solution in Python 3:
def repeatedString(s,n):
i = 0
c = 0
for i in s:
if i == 'a':
c += 1
q = int(n / len(s)) #Finding the quotient
r = int(n % len(s)) #Finding the remainder
if r == 0:
c *= q
else:
x = 0
for i in range(r):
if s[i] == 'a':
x += 1
c = c*q + x
return int(c)
s = input()
n = int(input())
print(repeatedString(s,n))
if character 'a' is present in a given string pattern, then its quite faster to get the repeated count for it and later based on the total length of final string mentioned, will be trying to repeat the given pattern for same number of times & hence will multiple the repeated count with number of times a string pattern is going to repeat. Importantly if final string input is in odd numbers then we need to identify the those odd pattern and separately count the occurance of character 'a' in odd string pattern. Finally summing up the total count ( even & odd ) will gives us the expected result
def repeatedString(s, n):
# Get the length of input string
strlen = len(s)
a_repeat = 0
# Get the total count of a repeated character from the input string
for i in range(0,strlen):
if s[i] == 'a':
a_repeat = a_repeat + 1
# Get the multiplier to make sure that desired input string length achieved
str_multiplier = int(n // strlen)
# Get the repeated count if new string is been created
result = a_repeat*str_multiplier
new_str = s[:int( n % strlen )]
# for odd length of string, get the remaining characters and find repated characters count and add up it to final count
for i in range(0, len(new_str)):
if new_str[i] == 'a':
result += 1
return result
For this problem,
Get the length of string s.
First, if conditions: constrain
Now, instead of using a loop to add to space and time complexity, we use basic math's. Find the quotient of n//Len (s). Now find the number of times "a" is used in our string.
We can multiply the quotient with this number to get the total "a" used. Now, we can find the remainder of the string and use slice to search for "a" in the string we have left in the last.
Add both to get our answer.
def repeatedString(s, n):
#finding quotient and remainder of division
str1=len(s)
remainder=0
if 1<=str1<=100 and 1<=n<=10**12:
quotient= n//str1
a_s = s.count("a")
if a_s==0:
return 0
else:
remainder=s[:n%str1].count('a')
return quotient*a_s + remainder
Simple answer:
def repeatedString(s, n):
totalNumber = 0 // setting total of a's to 0
// using count function to find the total number of a's in the substring
totalNumber = s.count('a')
// finding how many number of times the substring fits in "n" and multiplying that by the number of a's we found earlier
totalNumber = n//len(s) * totalNumber
// if there is a remainder, we loop through the remainder string and add the number of "a's" found in that substring to the total
for i in s[:n%len(s)]:
if(i == "a"):
totalNumber +=1
return totalNumber

Python - Pull random numbers from a list. Populate a new list with a specified length and sum

I am trying to create a function where:
The output list is generated from random numbers from the input list
The output list is a specified length and adds to a specified sum
ex. I specify that I want a list that is 4 in length and adds up to 10. random numbers are pulled from the input list until the criteria is satisfied.
I feel like I am approaching this problem all wrong trying to use recursion. Any help will be greatly appreciated!!!
EDIT: for more context on this problem.... Its going to be a random enemy generator.
The end goal input list will be coming from a column in a CSV called XP. (I plan to use pandas module). But this CSV will have a list of enemy names in the one column, XP in another, Health in another, etc. So the end goal is to be able to specify the total number of enemies and what the sum XP should be between those enemies and have the list generate with the appropriate information. For ex. 5 enemies with a total of 200 XP between them. The result is maybe -> Apprentice Wizard(50 xp), Apprentice Wizard(50 xp), Grung(50), Xvart(25 xp), Xvart(25 xp). The output list will actually need to include all of the row information for the selected items. And it is totally fine to have duplicated in the output as seen in this example. That will actually make more sense in the narrative of the game that this is for.
The csv --> https://docs.google.com/spreadsheets/d/1PjnN00bikJfY7mO3xt4nV5Ua1yOIsh8DycGqed6hWD8/edit?usp=sharing
import random
from random import *
lis = [1,2,3,4,5,6,7,8,9,10]
output = []
def query (total, numReturns, myList, counter):
random_index = randrange(len(myList)-1)
i = myList[random_index]
h = myList[i]
# if the problem hasn't been solved yet...
if len(output) != numReturns and sum(output) != total:
print(output)
# if the length of the list is 0 (if we just started), then go ahead and add h to the output
if len(output) == 0 and sum(output) + h != total:
output.append(h)
query (total, numReturns, myList, counter)
#if the length of the output is greater than 0
if len(output) > 0:
# if the length plus 1 is less than or equal to the number numReturns
if len(output) +1 <= numReturns:
print(output)
#if the sum of list plus h is greater than the total..then h is too big. We need to try another number
if sum(output) + h > total:
# start counter
for i in myList:# try all numbers in myList...
print(output)
print ("counter is ", counter, " and i is", i)
counter += 1
print(counter)
if sum(output) + i == total:
output.append(i)
counter = 0
break
if sum(output) + i != total:
pass
if counter == len(myList):
del(output[-1]) #delete last item in list
print(output)
counter = 0 # reset the counter
else:
pass
#if the sum of list plus h is less than the total
if sum(output) + h < total:
output.append(h) # add h to the list
print(output)
query (total, numReturns, myList, counter)
if len(output) == numReturns and sum(output) == total:
print(output, 'It worked')
else:
print ("it did not work")
query(10, 4, lis, 0)
I guess that it would be better to get first all n-size combinations of given array which adds to specified number, and then randomly select one of them. Random selecting and checking if sum is equal to specified value, in pessimistic scenario, can last indefinitely.
from itertools import combinations as comb
from random import randint
x = [1,1,2,4,3,1,5,2,6]
def query(arr, total, size):
combs = [c for c in list(comb(arr, size)) if sum(c)==total]
return combs[randint(0, len(combs))]
#example 4-item array with items from x, which adds to 10
print(query(x, 10, 4))
If the numbers in your input list are consecutive numbers, then this is equivalent to the problem of choosing a uniform random output list of N integers in the range [min, max], where the output list is ordered randomly and min and max are the smallest and largest number in the input list. The Python code below shows how this can be solved. It has the following advantages:
It does not use rejection sampling.
It chooses uniformly at random from among all combinations that meet the requirements.
It's based on an algorithm by John McClane, which he posted as an answer to another question. I describe the algorithm in another answer.
import random # Or secrets
def _getSolTable(n, mn, mx, sum):
t = [[0 for i in range(sum + 1)] for j in range(n + 1)]
t[0][0] = 1
for i in range(1, n + 1):
for j in range(0, sum + 1):
jm = max(j - (mx - mn), 0)
v = 0
for k in range(jm, j + 1):
v += t[i - 1][k]
t[i][j] = v
return t
def intsInRangeWithSum(numSamples, numPerSample, mn, mx, sum):
""" Generates one or more combinations of
'numPerSample' numbers each, where each
combination's numbers sum to 'sum' and are listed
in any order, and each
number is in the interval '[mn, mx]'.
The combinations are chosen uniformly at random.
'mn', 'mx', and
'sum' may not be negative. Returns an empty
list if 'numSamples' is zero.
The algorithm is thanks to a _Stack Overflow_
answer (`questions/61393463`) by John McClane.
Raises an error if there is no solution for the given
parameters. """
adjsum = sum - numPerSample * mn
# Min, max, sum negative
if mn < 0 or mx < 0 or sum < 0:
raise ValueError
# No solution
if numPerSample * mx < sum:
raise ValueError
if numPerSample * mn > sum:
raise ValueError
if numSamples == 0:
return []
# One solution
if numPerSample * mx == sum:
return [[mx for i in range(numPerSample)] for i in range(numSamples)]
if numPerSample * mn == sum:
return [[mn for i in range(numPerSample)] for i in range(numSamples)]
samples = [None for i in range(numSamples)]
table = _getSolTable(numPerSample, mn, mx, adjsum)
for sample in range(numSamples):
s = adjsum
ret = [0 for i in range(numPerSample)]
for ib in range(numPerSample):
i = numPerSample - 1 - ib
# Or secrets.randbelow(table[i + 1][s])
v = random.randint(0, table[i + 1][s] - 1)
r = mn
v -= table[i][s]
while v >= 0:
s -= 1
r += 1
v -= table[i][s]
ret[i] = r
samples[sample] = ret
return samples
Example:
weights=intsInRangeWithSum(
# One sample
1,
# Count of numbers per sample
4,
# Range of the random numbers
1, 5,
# Sum of the numbers
10)
# Divide by 100 to get weights that sum to 1
weights=[x/20.0 for x in weights[0]]

How to apply recursion to this code about the number of ways to sum up to 'N'?

Given a list of integers, and a target integer N, I want to find the number of ways in which the integers in the list can be added to get N. Repetition is allowed.
This is the code:
def countWays(arr, m, N):
count = [0 for i in range(N + 1)]
# base case
count[0] = 1
# Count ways for all values up
# to 'N' and store the result
# m=len(arr)
for i in range(1, N + 1):
for j in range(m):
# if i >= arr[j] then
# accumulate count for value 'i' as
# ways to form value 'i-arr[j]'
if (i >= arr[j]):
count[i] += count[i - arr[j]]
# required number of ways
return count[N]
(from Geeksforgeeks)
Any idea on how to do it using recursion and memoization?
The problem you are trying to solve is the same as the number of ways to make a change for an amount given a list of denominations. In your case, the amount is analogous to target number N and the denominations are analogous to the list of integers. Here is the recursive code. The link is https://www.geeksforgeeks.org/coin-change-dp-7/
# Returns the count of ways we can sum
# arr[0...m-1] coins to get sum N
def count(arr, m, N ):
# If N is 0 then there is 1
# solution (do not include any coin)
if (N == 0):
return 1
# If N is less than 0 then no
# solution exists
if (N < 0):
return 0;
# If there are no coins and N
# is greater than 0, then no
# solution exist
if (m <=0 and N >= 1):
return 0
# count is sum of solutions (i)
# including arr[m-1] (ii) excluding arr[m-1]
return count( arr, m - 1, N ) + count( arr, m, N-arr[m-1] );

Python Subset Sum Problem for Given Length of Elements

For given set, and sum, and length of elements,
I want to get the boolean value whether the set satisfy the condition
For example...
Input : set = [18,0,2,20], sum = 20, length = 2 <br>
Output : True (subset [18,2] satisfy the sum=20 for given length 2)
Input : set = [18,0,2,20], sum = 22, length = 1 <br>
Output : False
How can I solve the problem if there is a given length constraint?
(I can solve it easily if there is no length condition:
subset-sum-problem)
def isSubsetSum(set, n, sum):
if sum == 0:
return True
if (sum != 0) and (n == 0):
return False
if (set[n-1] > sum):
return isSubsetSum(set,n-1,sum)
# (a) including the last element
# (b) excluding the last element
# Not "AND", But "OR" !!!!!
return isSubsetSum(set,n-1,sum) or isSubsetSum(set,n-1,sum-set[n-1])
If you're allowed to use imported modules, itertools has a combinations function that can make this quite easy:
from itertools import combinations
set = [18,0,2,20]
total = 20
length = 2
result = [ c for c in combinations(set,length) if sum(c) == total ]
if result:
print("True, subset ",result[0],"satisfies the sum", total, "given length",length)
else:
print("False")
If you need it to be a recursive function, consider that for each element X in the set, if you can find a subset of N-1 elements in the subsequent elements that total sum-X, you have a solution for sum/length=N.
For example:
def subSum(numbers,total,length):
if len(numbers) < length or length < 1:
return []
for index,number in enumerate(numbers):
if length == 1 and number == total:
return [number]
subset = subSum(numbers[index+1:],total-number,length-1)
if subset:
return [number] + subset
return []
Use itertools.combinations:
from itertools import combinations
inp = [18,0,2,20]
length = 2
sum_ = 20
def isSubsetSum(data, length, sum_):
data = [i[0]+i[1] for i in combinations(data,length)]
if sum_ in data:
return True
return False
print(isSubsetSum(inp,length, sum_))

Categories