I've tried my best to obtain the powers and coefficients of an arbitrary polynomial given by user on a seperate list.
Basically, only the coefficient part is used and not the power part, but the list of powers(of variables is used for comparison only). I've done it and it works, but the code is kind of sloppy and non-elegant. Is there a better way to code this?
What is should basically do is:
When the user inputs say: 4x3+3 it should return something like:
coeffs = [4,0,0,3]
This is so that I can solve the polynomial using Horner's method.
Here's the runnable code: REPL CODE
The code is run with the test function as:
x = solve(function)
x.parse()
.
#!/usr/bin/python3
######################################################################
#code information
#
#
# When the user provides the input of the form
# 4x3+2x+1
# The parse method is expected to return
# A coefficient list of the provided polynomial
# in ready for use for the horner's method of solving
#######################################################################
function = "4x3+2x+1" #this is the sample input the user is expected to give
#
class solve:
def __init__(self, string):
self.function = string
self.letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u',
'v', 'w', 'x', 'y', 'z']
#######################################################################
#######################################################################
#######################################################################
#######################################################################
def parse(self):
signs = ['+', '-', '*']
for sign in signs:
self.function = self.function.replace(sign, ' ')#this is where all the
#signs are converted
#to spaces
self.function = self.function.split() #this is where all the
#list is split into terms
self.function.sort(reverse = True) #the polynomial is sorted always
#in the decreasing order
#from higher to lower order of x
coeffs = [] #list that holds all the coefficients
powers = [] #list that holds all the powers
while self.function:
term = self.function.pop(0)#for each term in the polynomial
for letter in self.letters:
#check for the alphabets in the letters(The list above)
if letter in term:
x, y = term.split(letter)
coeffs.append(int(x))#append the coefficient to the list
if y != '':
powers.append(int(y))#append the power to the list
else:
powers.append(1) #append 1 for x ^ 1 term
else:
try:
temp = int(term) #exception occurs here
coeffs.append(temp)#append constant term after exhaution
#of all the polynomial terms
#if no constants exits
#this is not reached
#and neither the line
#directly below
powers.append(0)#only for a constant,we have power 0
break #break nonsense to append only once
except:
pass #exception passed silently
return self.check_complete(coeffs, powers)
print("The coefficients are: ", coeffs)
print("The powers are: ", powers)
#######################################################################
#######################################################################
#######################################################################
#######################################################################
def check_complete(self, coeffs, powers):
"""This function checks if the polynomial is a
complete polynomial that is if it has all the powers of x
it does this by comparing the two lists hand in hand,
that is checks the corresponding terms"""
try:
#while the function arrives here
#power and range are assumed to be of same length
factor = 0 #factor for keeping track of index below
for index in range(len(powers)):
########################################
########################################
Index = index + factor #just cleaning up
########################################
########################################
difference = powers[Index] - powers[Index+1]
while difference > 1:
factor += 1 #factor incremented to keep track
#of where to add
difference -= 1
coeffs.insert(Index+1, 0)#in the coefficient list
#insert zeros where the
#polynomial is missing a term
except:
return coeffs #pass the exception
Yes, you've made this far too complicated. Also, I think you've made an error in the parsing, in that you treat all operators as if they were addition: you change them to spaces and then ignore the differences. I'd test this, but you failed to supply a MCVE.
I suggest some simple steps. Consider the polynomial 1+4x3-2x.
From your text, I gather that you allow only a single variable of a single lower-case letter. Don't go through the trouble of defining an alphabet (which is already in a system package, anyway); simply find the one letter in the string, and store that as the separator, sep.
Scan the string, dividing at any plus or minus sign; keep the sign. This should yield the list ["1", "+4x3", "-2x"].
Scan the list; for any string without the sep variable, append "x0"; for any with no number ahead of sep, prepend a "1"; for any with no number after sep, append a "1"; for any without a leading sign (that can be only the first element of the list", prepend a "+". We now have ["+1x0", "+4x3", "-2x1"].
Now, scan each element of the list. Split at sep and convert the elements to a tuple of integers. [(1, 0), (4, 3), (-2, 1)].
Finally, build your list of coefficients. Let's call the list of tuples terms. Get the highest power and make that the max index of a list of 0's. Then simply assign each coefficient to the location of the corresponding power.
Code:
size = max[z[1] for z in terms] + 1
coeff = [0]*size
for term in terms:
coeff[term[1]] = term[0]
Related
I have a string that goes like this
string = "CCB"
and a list
list = ['C','C','B','CC']
How do i sort them by their appearance order in the string (high priority) and their length(lower priority). After sorted the list should be like this
list = ['C' , 'C ', 'CC' , 'B']
I'm having some problem with this. does anyone have a python function or how to implement this problem?
One method is to create tuples of the indices and length before sorting, then reducing to the original input after. Below is one such example of doing this. Note that if the index is not found, we assume that it should come at the end and then just be sorted by length.
def sortby_index_length(input, items):
def index_or_large(haystack, needle):
try:
return haystack.index(needle)
except ValueError:
return len(haystack)
indexes = list(map(lambda x: (x, index_or_large(input, x)), items))
indexes.sort(key=lambda xy: (xy[1], len(xy[0])))
return list(map(lambda x: x[0], indexes))
print(sortby_index_length("CCB", ['C','C','B','CC']))
Which gives the expected output of ['C', 'C', 'CC', 'B']. This also uses the sort function where we specify the sorting ordering to be index tie broken by length.
Given a string sequence which contains only four letters, ['a','g','c','t']
for example: agggcttttaaaatttaatttgggccc.
Find all the shortest unique sub-string of the string sequence which are of equal length (the length should be minimum of all the unique sub-strings) ?
For example : aaggcgccttt
answer: ['aa', 'ag', 'gg','cg', 'cc','ct']
explanation:shortest unique sub-string of length 2
I have tried using suffix-arrays coupled with longest common prefix but i am unable to draw the solution perfectly.
I'm not sure what you mean by "minimum unique sub-string", but looking at your example I assume you mean "shortest runs of a single letter". If this is the case, you just need to iterate through the string once (character by character) and count all the shortest runs you find. You should keep track of the length of the minimum run found so far (infinity at start) and the length of the current run.
If you need to find the exact runs, you can add all the minimum runs you find to e.g. a list as you iterate through the string (and modify that list accordingly if a shorter run is found).
EDIT:
I thought more about the problem and came up with the following solution.
We find all the unique sub-strings of length i (in ascending order). So, first we consider all sub-strings of length 1, then all sub-strings of length 2, and so on. If we find any, we stop, since the sub-string length can only increase from this point.
You will have to use a list to keep track of the sub-strings you've seen so far, and a list to store the actual sub-strings. You will also have to maintain them accordingly as you find new sub-strings.
Here's the Java code I came up with, in case you need it:
String str = "aaggcgccttt";
String curr = "";
ArrayList<String> uniqueStrings = new ArrayList<String>();
ArrayList<String> alreadySeen = new ArrayList<String>();
for (int i = 1; i < str.length(); i++) {
for (int j = 0; j < str.length() - i + 1; j++) {
curr = str.substring(j, j + i);
if (!alreadySeen.contains(curr)){ //Sub-string hasn't been seen yet
uniqueStrings.add(curr);
alreadySeen.add(curr);
}
else //Repeated sub-string found
uniqueStrings.remove(curr);
}
if (!uniqueStrings.isEmpty()) //We have found non-repeating sub-string(s)
break;
alreadySeen.clear();
}
//Output
if (uniqueStrings.isEmpty())
System.out.println(str);
else {
for (String s : uniqueStrings)
System.out.println(s);
}
The uniqueStrings list contains all the unique sub-strings of minimum length (used for output). The alreadySeen list keeps track of all the sub-strings that have already been seen (used to exclude repeating sub-strings).
I'll write some code in Python, because that's what I find the easiest.
I actually wrote both the overlapping and the non-overlapping variants. As a bonus, it also checks that the input is valid.
You seems to be interested only in the overlapping variant:
import itertools
def find_all(
text,
pattern,
overlap=False):
"""
Find all occurrencies of the pattern in the text.
Args:
text (str|bytes|bytearray): The input text.
pattern (str|bytes|bytearray): The pattern to find.
overlap (bool): Detect overlapping patterns.
Yields:
position (int): The position of the next finding.
"""
len_text = len(text)
offset = 1 if overlap else (len(pattern) or 1)
i = 0
while i < len_text:
i = text.find(pattern, i)
if i >= 0:
yield i
i += offset
else:
break
def is_valid(text, tokens):
"""
Check if the text only contains the specified tokens.
Args:
text (str|bytes|bytearray): The input text.
tokens (str|bytes|bytearray): The valid tokens for the text.
Returns:
result (bool): The result of the check.
"""
return set(text).issubset(set(tokens))
def shortest_unique_substr(
text,
tokens='acgt',
overlapping=True,
check_valid_input=True):
"""
Find the shortest unique substring.
Args:
text (str|bytes|bytearray): The input text.
tokens (str|bytes|bytearray): The valid tokens for the text.
overlap (bool)
check_valid_input (bool): Check if the input is valid.
Returns:
result (set): The set of the shortest unique substrings.
"""
def add_if_single_match(
text,
pattern,
result,
overlapping):
match_gen = find_all(text, pattern, overlapping)
try:
next(match_gen) # first match
except StopIteration:
# the pattern is not found, nothing to do
pass
else:
try:
next(match_gen)
except StopIteration:
# the pattern was found only once so add to results
result.add(pattern)
else:
# the pattern is found twice, nothing to do
pass
# just some sanity check
if check_valid_input and not is_valid(text, tokens):
raise ValueError('Input text contains invalid tokens.')
result = set()
# shortest sequence cannot be longer than this
if overlapping:
max_lim = len(text) // 2 + 1
max_lim = len(tokens)
for n in range(1, max_lim + 1):
for pattern_gen in itertools.product(tokens, repeat=2):
pattern = ''.join(pattern_gen)
add_if_single_match(text, pattern, result, overlapping)
if len(result) > 0:
break
else:
max_lim = len(tokens)
for n in range(1, max_lim + 1):
for i in range(len(text) - n):
pattern = text[i:i + n]
add_if_single_match(text, pattern, result, overlapping)
if len(result) > 0:
break
return result
After some sanity check for the correctness of the outputs:
shortest_unique_substr_ovl = functools.partial(shortest_unique_substr, overlapping=True)
shortest_unique_substr_ovl.__name__ = 'shortest_unique_substr_ovl'
shortest_unique_substr_not = functools.partial(shortest_unique_substr, overlapping=False)
shortest_unique_substr_not.__name__ = 'shortest_unique_substr_not'
funcs = shortest_unique_substr_ovl, shortest_unique_substr_not
test_inputs = (
'aaa',
'aaaa',
'aaggcgccttt',
'agggcttttaaaatttaatttgggccc',
)
import functools
for func in funcs:
print('Func:', func.__name__)
for test_input in test_inputs:
print(func(test_input))
print()
Func: shortest_unique_substr_ovl
set()
set()
{'cg', 'ag', 'gg', 'ct', 'aa', 'cc'}
{'tg', 'ag', 'ct'}
Func: shortest_unique_substr_not
{'aa'}
{'aaa'}
{'cg', 'tt', 'ag', 'gg', 'ct', 'aa', 'cc'}
{'tg', 'ag', 'ct', 'cc'}
it is wise to benchmark how fast we actually are.
Below you can find some benchmarks, produced using some template code from here (the overlapping variant is in blue):
and the rest of the code for completeness:
def gen_input(n, tokens='acgt'):
return ''.join([tokens[random.randint(0, len(tokens) - 1)] for _ in range(n)])
def equal_output(a, b):
return a == b
input_sizes = tuple(2 ** (1 + i) for i in range(16))
runtimes, input_sizes, labels, results = benchmark(
funcs, gen_input=gen_input, equal_output=equal_output,
input_sizes=input_sizes)
plot_benchmarks(runtimes, input_sizes, labels, units='ms')
plot_benchmarks(runtimes, input_sizes, labels, units='μs', zoom_fastest=2)
As far as the asymptotic time-complexity analysis is concerned, considering only the overlapping case, let N be the input size, let K be the number of tokens (4 in your case), find_all() is O(N), and the body of shortest_unique_substr is O(K²) (+ O((K - 1)²) + O((K - 2)²) + ...).
So, this is overall O(N*K²) or O(N*(Σk²)) (for k = 1, …, K), since K is fixed, this is O(N), as the benchmarks seem to indicate.
I tried SecureRandom.random_number(9**6) but it sometimes returns 5 and sometimes 6 numbers. I'd want it to be a length of 6 consistently. I would also prefer it in the format like SecureRandom.random_number(9**6) without using syntax like 6.times.map so that it's easier to be stubbed in my controller test.
You can do it with math:
(SecureRandom.random_number(9e5) + 1e5).to_i
Then verify:
100000.times.map do
(SecureRandom.random_number(9e5) + 1e5).to_i
end.map { |v| v.to_s.length }.uniq
# => [6]
This produces values in the range 100000..999999:
10000000.times.map do
(SecureRandom.random_number(9e5) + 1e5).to_i
end.minmax
# => [100000, 999999]
If you need this in a more concise format, just roll it into a method:
def six_digit_rand
(SecureRandom.random_number(9e5) + 1e5).to_i
end
To generate a random, 6-digit string:
# This generates a 6-digit string, where the
# minimum possible value is "000000", and the
# maximum possible value is "999999"
SecureRandom.random_number(10**6).to_s.rjust(6, '0')
Here's more detail of what's happening, shown by breaking the single line into multiple lines with explaining variables:
# Calculate the upper bound for the random number generator
# upper_bound = 1,000,000
upper_bound = 10**6
# n will be an integer with a minimum possible value of 0,
# and a maximum possible value of 999,999
n = SecureRandom.random_number(upper_bound)
# Convert the integer n to a string
# unpadded_str will be "0" if n == 0
# unpadded_str will be "999999" if n == 999999
unpadded_str = n.to_s
# Pad the string with leading zeroes if it is less than
# 6 digits long.
# "0" would be padded to "000000"
# "123" would be padded to "000123"
# "999999" would not be padded, and remains unchanged as "999999"
padded_str = unpadded_str.rjust(6, '0')
Docs to Ruby SecureRand, lot of cool tricks here.
Specific to this question I would say: (SecureRandom.random_number * 1000000).to_i
Docs: random_number(n=0)
If 0 is given or an argument is not given, ::random_number returns a float: 0.0 <= ::random_number < 1.0.
Then multiply by 6 decimal places (* 1000000) and truncate the decimals (.to_i)
If letters are okay, I prefer .hex:
SecureRandom.hex(3) #=> "e15b05"
Docs:
hex(n=nil)
::hex generates a random hexadecimal string.
The argument n specifies the length, in bytes, of the random number to
be generated. The length of the resulting hexadecimal string is twice
n.
If n is not specified or is nil, 16 is assumed. It may be larger in
future.
The result may contain 0-9 and a-f.
Other options:
SecureRandom.uuid #=> "3f780c86-6897-457e-9d0b-ef3963fbc0a8"
SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
For Rails apps creating a barcode or uid with an object you can do something like this in the object model file:
before_create :generate_barcode
def generate_barcode
begin
return if self.barcode.present?
self.barcode = SecureRandom.hex.upcase
end while self.class.exists?(barcode: barcode)
end
SecureRandom.random_number(n) gives a random value between 0 to n. You can achieve it using rand function.
2.3.1 :025 > rand(10**5..10**6-1)
=> 742840
rand(a..b) gives a random number between a and b. Here, you always get a 6 digit random number between 10^5 and 10^6-1.
I'm trying to find a efficient algorithm to get all ways to partition a string
eg for a given string 'abcd' =>
'a' 'bcd'
'a' 'b' 'cd'
'a' 'b' 'c' 'd'
'ab' 'cd'
'ab' 'c' 'd'
'abc' 'd'
'a', 'bc', 'd
any language would be appreciated
Thanks in advance !
Problem analysis
Between each pair of adjacent characters, you can decide whether to cut. For a string of size n, there are n-1 positions where you can cut or not, i.e. there are two possibilities. Therefore a string of size n can be partitioned in 2n-1 ways.
The output consists of 2n-1 partitions, each having n characters plus separators. So we can describe the output size as f(n) = 2n-1 * n + s(n) where s(n) ≥ 0 accounts for the partition separators and line separators.
So due to the output size alone, an algorithm solving this problem must have exponential runtime or worse: Ω(2n).
(0 ≤ c * 2n = ½ * 2n = 2n-1 ≤ 2n-1 * n ≤ f(n) for all n≥k with positive constants c=½, k=1)
Solution
I chose to represent a partition as integer. Each bit in cutpoints determines whether to cut between characters i and i+1. To iterate through all possible partitions, we just need to go trough all integers between 0 and 2^(n-1) - 1.
Example: For a string of length 4, we go through all integers between 0 and 2^3 - 1 or 0 and 7 or in binary: 000 and 111.
# (python 2 or 3)
def all_partitions(string):
for cutpoints in range(1 << (len(string)-1)):
result = []
lastcut = 0
for i in range(len(string)-1):
if (1<<i) & cutpoints != 0:
result.append(string[lastcut:(i+1)])
lastcut = i+1
result.append(string[lastcut:])
yield result
for partition in all_partitions("abcd"):
print(partition)
Memory usage:
I think my solution uses O(n) memory with Python 3. Only one partition is generated at a time, it's printed and not referenced anymore. This changes of course, if you keep all results, e.g. by storing them in a list.
In Python 2 replace range with xrange, otherwise all possible cutpoints will be stored in a list, therefore needing an exponential amount of memory.
JavaScript solution
// ES6 generator
function* all_partitions(string) {
for (var cutpoints = 0; cutpoints < (1 << (string.length - 1)); cutpoints++) {
var result = [];
var lastcut = 0;
for (var i = 0; i < string.length - 1; i++) {
if (((1 << i) & cutpoints) !== 0) {
result.push(string.slice(lastcut, i + 1));
lastcut = i + 1;
}
}
result.push(string.slice(lastcut));
yield result;
}
}
for (var partition of all_partitions("abcd")) {
console.log(partition);
}
Tested with NodeJS v4.4.3 (disclaimer: I have not used NodeJS before).
GeeksforGeeks has provided a well-explained solution to this problem:
For string abcd there will be 2^(n-1) i.e. 8 partitions.
(a)(b)(c)(d)
(a)(b)(cd)
(a)(bc)(d)
(a)(bcd)
(ab)(c)(d)
(ab)(cd)
(abc)(d)
(abcd)
The crux of the solution lies in the recursion to print all the permutations.
maintain two parameters – index of the next character to be processed and the output string so far. We start from index of next character to be processed, append substring formed by unprocessed string to the output string and recurse on remaining string until we process the whole string.
// Java program to find all combinations of Non-
// overlapping substrings formed from given
// string
class GFG
{
// find all combinations of non-overlapping
// substrings formed by input string str
static void findCombinations(String str, int index,
String out)
{
if (index == str.length())
System.out.println(out);
for (int i = index; i < str.length(); i++)
// append substring formed by str[index,
// i] to output string
findCombinations(str, i + 1, out +
"(" + str.substring(index, i+1) + ")" );
}
// driver program
public static void main (String[] args)
{
// input string
String str = "abcd";
findCombinations(str, 0, "");
}
}
Time Complexity is O(2^n)
Here's the link to the article: http://www.geeksforgeeks.org/print-ways-break-string-bracket-form/
I just wanted to post a simple recursive solution to this problem for anyone stumbling on this question. Probably not the best way, but this was way simpler for me to understand and implement. If I am wrong, please correct me.
def party(s:str, P:list, res:list) -> None :
"""Recursively generates all partitions of a given string"""
res.append(P+[s])
for i in range(1,len(s)):
party(s[i:],P+[s[:i]],res)
res = []
party("abcd",[],res)
print(res)
"""
[['abcd'], ['a', 'bcd'], ['a', 'b', 'cd'], ['a', 'b', 'c', 'd'],
['a', 'bc', 'd'], ['ab', 'cd'], ['ab', 'c', 'd'], ['abc', 'd']]
"""
It works as follows:
Given a string or a substring of it, we can split after each of its character creating two halves.
Say: "abc" can be partitioned into ["a","bc"], ["ab","c"]
We save the first part in a intermediate partition P and
recursively call party on the other half.
Because both halves together form a complete partition we save it to res.
Example:
initially: s = "abc" is a valid partition, save it to res.
recr call: s = "bc", P = ["a"] , so P +[s]= ["a","bc"] is also valid, save it to res.
Proceed with splitting "bc".
P = ["a","b"], s="c" so P + [s] is also valid. And so on..
recr call 3: s = "c", P = ["ab"], so P + [s] =["ab","c"] is also valid, save it to res
Working:
tests = ["abc","abcd","a"]
for t in tests:
res = []
party(t,[],res)
print(f'{t} -> {res} \n')
"""Output
abc -> [['abc'], ['a', 'bc'], ['a', 'b', 'c'], ['ab', 'c']]
abcd -> [['abcd'], ['a', 'bcd'], ['a', 'b', 'cd'], ['a', 'b', 'c', 'd'],
['a', 'bc', 'd'], ['ab', 'cd'], ['ab', 'c', 'd'], ['abc', 'd']]
a -> [['a']]
"""
This is a solution which minimizes developer time by taking advantage of a built-in iterator. It should be reasonably quick for problem sizes for which the answer itself is not infeasibly large.
There is a one-to-one correspondence between partitions of a string and subsets of potential cutpoints. If the length of the string is n then there are n-1 places where you could cut the string. A straightforward way would be to iterate through such subsets, and for each such subset, slice the string in that way. Here is a Python approach which uses the standard modules itertools:
import itertools
def multiSlice(s,cutpoints):
k = len(cutpoints)
if k == 0:
return [s]
else:
multislices = [s[:cutpoints[0]]]
multislices.extend(s[cutpoints[i]:cutpoints[i+1]] for i in range(k-1))
multislices.append(s[cutpoints[k-1]:])
return multislices
def allPartitions(s):
n = len(s)
cuts = list(range(1,n))
for k in range(n):
for cutpoints in itertools.combinations(cuts,k):
yield multiSlice(s,cutpoints)
For example:
>>> parts = allPartitions('World')
>>> for p in parts: print(p)
['World']
['W', 'orld']
['Wo', 'rld']
['Wor', 'ld']
['Worl', 'd']
['W', 'o', 'rld']
['W', 'or', 'ld']
['W', 'orl', 'd']
['Wo', 'r', 'ld']
['Wo', 'rl', 'd']
['Wor', 'l', 'd']
['W', 'o', 'r', 'ld']
['W', 'o', 'rl', 'd']
['W', 'or', 'l', 'd']
['Wo', 'r', 'l', 'd']
['W', 'o', 'r', 'l', 'd']
Note that this approach produces generates ['World'] as a partition of 'World'. This corresponds to slicing with an empty set of cut points. I regard that as a feature rather than a bug since the standard mathematical definition of partition allows for a partition of a set into one piece. If this in undesirable for your purposes, the fix is easy enough -- just iterate over the nonempty subsets of the cut points. In terms of the above code, this fix amounts to adding two characters to allPartitions: replace
for k in range(n):
by
for k in range(1,n):
Something along the lines of the following (untested and likely buggy VB.NET sample)
Function FindAllGroups(s As String) As List(Of List(Of String))
Dim ret As New List(Of List(Of String))
Dim l As New List(Of String)
l.Add(s) 'the whole string unbroken
ret.Add(l) 'first option we return is the whole unbroken string by itself
If s.Length > 1 Then
Dim tmp = FindAllGroups(s.Substring(1)) 'find all the groups for the rest of the string after the first character
For Each l2 in tmp
l = l2.ToList 'Copy it
l.Insert(s.SubString(0,1),0)'insert the first character from this string by itself before this combination for the rest of the string
ret.Add(l)
Next
For Each l2 in tmp
l = l2.ToList 'Copy it
l(0)= s.SubString(0,1) & l(0) 'insert the first character from this string as part of the first element in the list
ret.Add(l)
Next
End If
Return ret
End Function
This basically works by saying that we can take 'abcd' and split it into
'a', 1st option for 'bcd' split
'a', 2nd option for 'bcd' split
...
+
1st option for 'bcd' split with the first element prepended with 'a'
2nd option for 'bcd' split with the first element prepended with 'a'
...
then to calculate 'bcd', we just repeat the process as above, only with
'b', 1st option for 'cd' split
'b', 2nd option for 'cd' split
...
+
1st option for 'cd' split with the first element prepended with 'b'
2nd option for 'cd' split with the first element prepended with 'b'
...
etc. repeated recursively.
However, this code isn't particularly efficient at runtime. One thing that you could do to speed it up significantly would be to add a Dictionary(Of String, List(Of List(Of String)) outside the function which you can store a cache of the results in and if the item exists in there, you return from there, if not, calculate it and add it. Lists also might not be the most efficient, and the ToList function might not be the quickest way of cloning. However, I've simplified it to make it easier to understand and also to save me time working it out!
This is a fairly standard depth first search (backtracking) problem.
void dfs(int startIndex, const string& s, vector<string>& tmp,
vector<vector<string>>& res){
if (startIndex == s.size()) {
res.push_back(tmp);
return;
}
for (int i = 1; startIndex + i <= s.size(); ++i) {
tmp.push_back(s.substr(startIndex, i));
dfs(startIndex + i, s, tmp, res);
tmp.pop_back();
}
}
int main()
{
vector<vector<string>> res;
vector<string> tmp;
string s = "abcd";
dfs(0, s, tmp, res);
}
For its execution and result please refer to here.
#include <bits/stdc++.h>
using namespace std;
vector<string> ans;
string s;
void solve(int previouscut, int len)
{
if(previouscut == s.length()) // base case
{
for(auto str:ans)
cout << str << " " ;
cout << "\n";
return;
}
if(previouscut+len>s.length()) // boundary case
return;
//cut
ans.push_back(s.substr(previouscut,len));
solve(previouscut + len,1);
ans.pop_back(); //backtrack
// no cut
solve(previouscut, len+1);
}
int main()
{
cin >> s;
solve(0,1);
return 0;
}
https://www.geeksforgeeks.org/substring-in-cpp/#
Given a non-negative integer n and an arbitrary set of inequalities that are user-defined (in say an external text file), I want to determine whether n satisfies any inequality, and if so, which one(s).
Here is a points list.
n = 0: 1
n < 5: 5
n = 5: 10
If you draw a number n that's equal to 5, you get 10 points.
If n less than 5, you get 5 points.
If n is 0, you get 1 point.
The stuff left of the colon is the "condition", while the stuff on the right is the "value".
All entries will be of the form:
n1 op n2: val
In this system, equality takes precedence over inequality, so the order that they appear in will not matter in the end. The inputs are non-negative integers, though intermediary and results may not be non-negative. The results may not even be numbers (eg: could be strings). I have designed it so that will only accept the most basic inequalities, to make it easier for writing a parser (and to see whether this idea is feasible)
My program has two components:
a parser that will read structured input and build a data structure to store the conditions and their associated results.
a function that will take an argument (a non-negative integer) and return the result (or, as in the example, the number of points I receive)
If the list was hardcoded, that is an easy task: just use a case-when or if-else block and I'm done. But the problem isn't as easy as that.
Recall the list at the top. It can contain an arbitrary number of (in)equalities. Perhaps there's only 3 like above. Maybe there are none, or maybe there are 10, 20, 50, or even 1000000. Essentially, you can have m inequalities, for m >= 0
Given a number n and a data structure containing an arbitrary number of conditions and results, I want to be able to determine whether it satisfies any of the conditions and return the associated value. So as with the example above, if I pass in 5, the function will return 10.
They condition/value pairs are not unique in their raw form. You may have multiple instances of the same (in)equality but with different values. eg:
n = 0: 10
n = 0: 1000
n > 0: n
Notice the last entry: if n is greater than 0, then it is just whatever you got.
If multiple inequalities are satisfied (eg: n > 5, n > 6, n > 7), all of them should be returned. If that is not possible to do efficiently, I can return just the first one that satisfied it and ignore the rest. But I would like to be able to retrieve the entire list.
I've been thinking about this for a while and I'm thinking I should use two hash tables: the first one will store the equalities, while the second will store the inequalities.
Equality is easy enough to handle: Just grab the condition as a key and have a list of values. Then I can quickly check whether n is in the hash and grab the appropriate value.
However, for inequality, I am not sure how it will work. Does anyone have any ideas how I can solve this problem in as little computational steps as possible? It's clear that I can easily accomplish this in O(n) time: just run it through each (in)equality one by one. But what happens if this checking is done in real-time? (eg: updated constantly)
For example, it is pretty clear that if I have 100 inequalities and 99 of them check for values > 100 while the other one checks for value <= 100, I shouldn't have to bother checking those 99 inequalities when I pass in 47.
You may use any data structure to store the data. The parser itself is not included in the calculation because that will be pre-processed and only needs to be done once, but if it may be problematic if it takes too long to parse the data.
Since I am using Ruby, I likely have more flexible options when it comes to "messing around" with the data and how it will be interpreted.
class RuleSet
Rule = Struct.new(:op1,:op,:op2,:result) do
def <=>(r2)
# Op of "=" sorts before others
[op=="=" ? 0 : 1, op2.to_i] <=> [r2.op=="=" ? 0 : 1, r2.op2.to_i]
end
def matches(n)
#op2i ||= op2.to_i
case op
when "=" then n == #op2i
when "<" then n < #op2i
when ">" then n > #op2i
end
end
end
def initialize(text)
#rules = text.each_line.map do |line|
Rule.new *line.split(/[\s:]+/)
end.sort
end
def value_for( n )
if rule = #rules.find{ |r| r.matches(n) }
rule.result=="n" ? n : rule.result.to_i
end
end
end
set = RuleSet.new( DATA.read )
-1.upto(8) do |n|
puts "%2i => %s" % [ n, set.value_for(n).inspect ]
end
#=> -1 => 5
#=> 0 => 1
#=> 1 => 5
#=> 2 => 5
#=> 3 => 5
#=> 4 => 5
#=> 5 => 10
#=> 6 => nil
#=> 7 => 7
#=> 8 => nil
__END__
n = 0: 1
n < 5: 5
n = 5: 10
n = 7: n
I would parse the input lines and separate them into predicate/result pairs and build a hash of callable procedures (using eval - oh noes!). The "check" function can iterate through each predicate and return the associated result when one is true:
class PointChecker
def initialize(input)
#predicates = Hash[input.split(/\r?\n/).map do |line|
parts = line.split(/\s*:\s*/)
[Proc.new {|n| eval(parts[0].sub(/=/,'=='))}, parts[1].to_i]
end]
end
def check(n)
#predicates.map { |p,r| [p.call(n) ? r : nil] }.compact
end
end
Here is sample usage:
p = PointChecker.new <<__HERE__
n = 0: 1
n = 1: 2
n < 5: 5
n = 5: 10
__HERE__
p.check(0) # => [1, 5]
p.check(1) # => [2, 5]
p.check(2) # => [5]
p.check(5) # => [10]
p.check(6) # => []
Of course, there are many issues with this implementation. I'm just offering a proof-of-concept. Depending on the scope of your application you might want to build a proper parser and runtime (instead of using eval), handle input more generally/gracefully, etc.
I'm not spending a lot of time on your problem, but here's my quick thought:
Since the points list is always in the format n1 op n2: val, I'd just model the points as an array of hashes.
So first step is to parse the input point list into the data structure, an array of hashes.
Each hash would have values n1, op, n2, value
Then, for each data input you run through all of the hashes (all of the points) and handle each (determining if it matches to the input data or not).
Some tricks of the trade
Spend time in your parser handling bad input. Eg
n < = 1000 # no colon
n < : 1000 # missing n2
x < 2 : 10 # n1, n2 and val are either number or "n"
n # too short, missing :, n2, val
n < 1 : 10x # val is not a number and is not "n"
etc
Also politely handle non-numeric input data
Added
Re: n1 doesn't matter. Be careful, this could be a trick. Why wouldn't
5 < n : 30
be a valid points list item?
Re: multiple arrays of hashes, one array per operator, one hash per point list item -- sure that's fine. Since each op is handled in a specific way, handling the operators one by one is fine. But....ordering then becomes an issue:
Since you want multiple results returned from multiple matching point list items, you need to maintain the overall order of them. Thus I think one array of all the point lists would be the easiest way to do this.