Working through nested loops - algorithm

Is there a way to find all the primes between 0 to 100 without actually using nested loops, i.e. with time complexity of less than n^2. I did try recursion but it still is same with same complexity. can anyone help please.
Thanks

A very useful implementation is to pre-calculate the list.
my #primes = (
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
);
say for #primes;
Obvious? Maybe, but I bet many people are about to post far more complex, and slower solutions.

Yes, look at the Seive of Atkin, which is an optimized version of the Sieve of Eratosthenes.
Python implementation:
import math
def sieveOfAtkin(limit):
P = [2,3]
sieve=[False]*(limit+1)
for x in range(1,int(math.sqrt(limit))+1):
for y in range(1,int(math.sqrt(limit))+1):
n = 4*x**2 + y**2
if n<=limit and (n%12==1 or n%12==5) : sieve[n] = not sieve[n]
n = 3*x**2+y**2
if n<= limit and n%12==7 : sieve[n] = not sieve[n]
n = 3*x**2 - y**2
if x>y and n<=limit and n%12==11 : sieve[n] = not sieve[n]
for x in range(5,int(math.sqrt(limit))):
if sieve[x]:
for y in range(x**2,limit+1,x**2):
sieve[y] = False
for p in range(5,limit):
if sieve[p] : P.append(p)
return P
print sieveOfAtkin(100)

Not exactly improvement from O(n^2)
But you can narrow down your search like this:
Prime numbers > 6 have a property. They are either 6n+1 or 6n-1(It does not mean that all 6n+1 or 6n-1s are prime numbers)
So your code would look like:
/**
* #author anirbanroy
*/
object PrimeNumberPrinter {
def main(args: Array[String]) {
var count: Int = 0
var initialPrimeNumberCount: Array[Int] = Array(0, 0, 1, 2, 2)
println("Enter a range: ")
val input = io.StdIn.readInt()
if (input > 4) {
count = 2;
for (i <- 5 to input by 6) {
if (i + 2 <= input) {
if (isPrime(i + 2)) {
count = count + 1
}
}
if (i <= input) {
if (isPrime(i)) {
count = count + 1
}
}
}
println("No of prime numbers: " + count)
} else {
println("No of prime numbers are: " + initialPrimeNumberCount(input))
}
}
def isPrime(value: Int): Boolean = {
val range: Int = round(sqrt(value).toFloat)
for (j <- 2 to range) {
if (value.%(j) == 0)
return false
}
return true
}

The brute force solution (trying to divide all odd integers by all odd divisors) doesn't have complexity O(N²), but O(N√N), as the search can stop when a tentative divisor exceeding √N has been reached.
You can pretty easily reduce this complexity by using the primes already identified, rather than all odd integers. Given the density function of the primes, you reduce to O(N√N/Log(N)).
Anyway, for N as small as 100, this "optimization" is not at all significant, as √N is only 10 and the prime divisors to be considered are 3, 5, 7, whereas the odd divisors would be 3, 5, 7, 9.
Here is a simple implementation that tries three divisors and does not attempt to stop when i>√N as this would add costly conditional branches.
N= 100
print 2, 3, 5, 7,
for i in range(3, N, 2):
if i % 3 != 0 and i % 5 != 0 and i % 7 != 0:
print i,
Technically speaking, this code is pure O(N), but only works until N<121. By direct counting, it performs exactly 106 modulo operations when using the shortcut evaluation of the and's.

Related

Approaching Dynamic Programming problem / Two restrictions

Given an array A of n integers and k <= n, we want to choose k numbers from this array and split them to pairs, such that the sum of the differences of those pairs (in absolute value) is minimal.
Example: If n = 8 and k = 6 and the array is A = [140, 100, 92, 21, 32, 48, 32, 100], then the optimal answer is 27.
Does someone have an idea?
Where do I start from in this problem?
I'm really bad at DP problems, so I would appreciate an informative answer describing the right approach to solve the problem.
Thanks in advance.
Sort elements. Now pairs ought to be made only with neighbors (for cases like 10,20,20,30 pairing 10/20 + 20/30 gives the same result as 10/30 + 20/20, for cases like 10,14,20 pair 10/20 is worse than 10/14 or 14/10)
Walk through array.
If pair is opened with the last element, we have the only possibility - close that pair with current element
If there is no opened pair and number of closed pairs is less than k/2, we have two possibilities - start pair or omit current element (if number of elements in the rest of array is larger than we must use), and we have to choose the best result from these cases.
So we can build recursion and then transform it into DP (code below is not DP yet, it builds full solution tree).
A = [140, 100, 92, 21, 32, 48, 32, 100]
n = len(A)
k = 6
def best(idx, openstate, pairsleft):
if pairsleft > (n - idx + 1)//2:
return 10000000
if pairsleft == 0:
return 0
if openstate:
return abs(A[idx] - A[idx-1]) + best(idx + 1, False, pairsleft - 1)
else:
return(min(best(idx + 1, True, pairsleft), best(idx + 1, False, pairsleft)))
A.sort()
print(best(0, False, k//2))
>> 27

Function which increases fast and slows down reaching predefined maximum

I am creating a count up algorithm where I increase the number with bigger increments and then the increments get smaller over time, ideally reaching zero or 1. The final sum value should be predefined. The number of steps should be an input parameter and can vary. It seems like it is a logarithmic function with a maximum value. However, the logarithmic function grows until infinity.
The best I've found is square root of logarithm:
val log = (1..10).map { Math.sqrt(Math.log(it * 1.0)) }
val max = log.max()
val rounded = log.map { it * 1000 / max!! }.map { Math.round(it) }
rounded.forEachIndexed { i, l ->
if (i + 1 < rounded.size)
println("${rounded[i + 1] - rounded[i]}")
}
However, i still do not get to very small increments in the end.
If range is from zero to 10:
549, 142, 85, 60, 46, 37, 31, 27, 23
If the range is 20:
481, 125, 74, 53, 40, 33, 27, 23, 21, 18, 16, 14, 14, 12, 11, 10, 10, 9, 9
What algorthm to use to get to 1 in the end?
Update:
Based on Patricks formula I made this solution:
` val N = 18981.0
val log = (1..50).map { N - N/it }
val max = log.max()
log.map { print("$it, ") }
val rounded = log.map { it * N / max!! }.map { Math.round(it) }`
It is important that N is Double and not the whole number
Square root of the logarithm also grows to infinity. Try
f(n) = N - N/n
This has the value 0 at n = 1 and tends towards N as n grows without bound. If you need finer granularity, add some coefficients and play around with them until you get something reasonable. For instance, you can use [1 + (n/1000)] and get similar but much slower growth. You can also use exp(-x) or any function with a horizontal asymptote and get similar behavior.
f(n) = N - exp(-n)
Again, add some coefficients and see how the function changes

Biggest sum of value for n stairs with value and use the given step

Given a staircase with n stairs each containing an integer value, e.g.,
staircase = [11, 22, 44, 5, 12, 34, 55, 45, 23, 64]
and given a set of possible step sizes for the staircase, e.g.,
possible_steps = {3,4,5}
I want to find the sequence of steps in order to maximize the sum of collected values. A value is collected once you step on a stair.
Example:
step_sequence is [3,4] , value is 44+55 = 99
step_sequence is [4,4,4] , value is 5+45+(out of index is 0) = 50
The best step_sequence is [3,4,4] which maximizes the collected values (44+55+64 = 163)
Question:
How can I use dynamic programming to solve the problem? Or is the best way to solve the problem with dynamic programming?
Yes you can solve it using dynamic programming. If n is the total amount of numbers in the staircase and m is the number of possible steps, then the solution will have time complexity O(nm) and space complexity O(n). The idea is to ask yourself what is the best sum I can get when the stairs are ending at index i. Kinda similar to the coin change problem.
function maxSum(stairs, steps) {
let dp = [], maxSteps = steps[0], globalBest = undefined
for (let i = 1; i < steps.length; i++)
if (steps[i] > maxSteps)
maxSteps = steps[i]
for (let i = 0; i < stairs.length; i++) {
let best = undefined
for (let j = 0; j < steps.length; j++) {
if (i - steps[j] == -1 && (best === undefined || best < stairs[i]))
best = stairs[i]
else if (i - steps[j] >= 0 && dp[i - steps[j]] !== undefined &&
(best === undefined || dp[i - steps[j]] + stairs[i] > best))
best = dp[i - steps[j]] + stairs[i]
}
dp[i] = best
if (best !== undefined && i + maxSteps >= stairs.length &&
(globalBest === undefined || globalBest < best))
globalBest = best
}
return globalBest
}
console.log(maxSum([11, 22, 44, 5, 12, 34, 55, 45, 23, 64], [3, 4, 5]))
There are some special cases, like when entering the stairs i - steps[j] == -1 or when checking if we can reach the end of stairs for the global max i + maxSteps >= stairs.length. The rest is pretty much standard dp.
This implementation also works with negative numbers on the staircase (the steps have to be positive). It is assumed you have to collect at least one number on the staircase, if that is not possible the function returns undefined.

Coin change with limited coins complexity

If there is an unlimited number of every coin then the complexity is O(n*m) where is n is the total change and m is the number of coin types. Now when the coins for every type are limited then we have to take into account the remaining coins. I managed to make it work with a complexity of O(n*m2) using another for of size n so I can track the remaining coins for each type. Is there a way-trick to make the complexity better? EDIT : The problem is to compute the least ammount of coins required to make the exact given change and the number of times that we used each coin type
There is no need for an extra loop. You need to:
recurse with a depth of at most m (number of coins) levels, dealing with one specific coin per recursion level.
Loop at most n times at each recursion level in order to decide how many you will take of a given coin.
Here is how the code would look in Python 3:
def getChange(coins, amount, coinIndex = 0):
if amount == 0:
return [] # success
if coinIndex >= len(coins):
return None # failure
coin = coins[coinIndex]
coinIndex += 1
# Start by taking as many as possible from this coin
canTake = min(amount // coin["value"], coin["count"])
# Reduce the number taken from this coin until success
for count in range(canTake, -1, -1): # count will go down to zero
# Recurse to decide how many to take from the next coins
change = getChange(coins, amount - coin["value"] * count, coinIndex)
if change != None: # We had success
if count: # Register this number for this coin:
return change + [{ "value": coin["value"], "count": count }]
return change
# Example data and call:
coins = [
{ "value": 20, "count": 2 },
{ "value": 10, "count": 2 },
{ "value": 5, "count": 3 },
{ "value": 2, "count": 2 },
{ "value": 1, "count": 10 }
]
result = getChange(coins, 84)
print(result)
Output for the given example:
[
{'value': 1, 'count': 5},
{'value': 2, 'count': 2},
{'value': 5, 'count': 3},
{'value': 10, 'count': 2},
{'value': 20, 'count': 2}
]
Minimising the number of coins used
As stated in comments, the above algorithm returns the first solution it finds. If there is a requirement that the number of individual coins must be minimised when there are multiple solutions, then you cannot return halfway a loop, but must retain the "best" solution found so far.
Here is the modified code to achieve that:
def getchange(coins, amount):
minCount = None
def recurse(amount, coinIndex, coinCount):
nonlocal minCount
if amount == 0:
if minCount == None or coinCount < minCount:
minCount = coinCount
return [] # success
return None # not optimal
if coinIndex >= len(coins):
return None # failure
bestChange = None
coin = coins[coinIndex]
# Start by taking as many as possible from this coin
cantake = min(amount // coin["value"], coin["count"])
# Reduce the number taken from this coin until 0
for count in range(cantake, -1, -1):
# Recurse, taking out this coin as a possible choice
change = recurse(amount - coin["value"] * count, coinIndex + 1,
coinCount + count)
# Do we have a solution that is better than the best so far?
if change != None:
if count: # Does it involve this coin?
change.append({ "value": coin["value"], "count": count })
bestChange = change # register this as the best so far
return bestChange
return recurse(amount, 0, 0)
coins = [{ "value": 10, "count": 2 },
{ "value": 8, "count": 2 },
{ "value": 3, "count": 10 }]
result = getchange(coins, 26)
print(result)
Output:
[
{'value': 8, 'count': 2},
{'value': 10, 'count': 1}
]
Here's an implementation of an O(nm) solution in Python.
If one defines C(c, k) = 1 + x^c + x^(2c) + ... + x^(kc), then the program calculates the first n+1 coefficients of the polynomial product(C(c[i], k[i]), i = 1...ncoins). The j'th coefficient of this polynomial is the number of ways of making change for j.
When all the ks are unlimited, this polynomial product is easy to calculate (see, for example: https://stackoverflow.com/a/20743780/1400793). When limited, one needs to be able to calculate running sums of k terms efficiently, which is done in the program using the rs array.
# cs is a list of pairs (c, k) where there's k
# coins of value c.
def limited_coins(cs, n):
r = [1] + [0] * n
for c, k in cs:
# rs[i] will contain the sum r[i] + r[i-c] + r[i-2c] + ...
rs = r[:]
for i in xrange(c, n+1):
rs[i] += rs[i-c]
# This line effectively performs:
# r'[i] = sum(r[i-j*c] for j=0...k)
# but using rs[] so that the computation is O(1)
# and in place.
r[i] += rs[i-c] - (0 if i<c*(k+1) else rs[i-c*(k+1)])
return r[n]
for n in xrange(50):
print n, limited_coins([(1, 3), (2, 2), (5, 3), (10, 2)], n)

Need an algorithm to split a series of numbers

After a few busy nights my head isn't working so well, but this needs to be fixed yesterday, so I'm asking the more refreshed community of SO.
I've got a series of numbers. For example:
1, 5, 7, 13, 3, 3, 4, 1, 8, 6, 6, 6
I need to split this series into three parts so the sum of the numbers in all parts is as close as possible. The order of the numbers needs to be maintained, so the first part must consist of the first X numbers, the second - of the next Y numbers, and the third - of whatever is left.
What would be the algorithm to do this?
(Note: the actual problem is to arrange text paragraphs of differing heights into three columns. Paragraphs must maintain order (of course) and they may not be split in half. The columns should be as equal of height as possible.)
First, we'll need to define the goal better:
Suppose the partial sums are A1,A2,A3, We are trying to minimize |A-A1|+|A-A2|+|A-A3|. A is the average: A=(A1+A2+A3)/3.
Therefore, we are trying to minimize |A2+A3-2A1|+|A1+A3-2A2|+|A1+A2-2A3|.
Let S denote the sum (which is constant): S=A1+A2+A3, so A3=S-A1-A2.
We're trying to minimize:
|A2+S-A1-A2-2A1|+|A1+S-A1-A2-2A2|+|A1+A2-2S+2A1+2A2|=|S-3A1|+|S-3A2|+|3A1+SA2-2S|
Denoting this function as f, we can do two loops O(n^2) and keep track of the minimum:
Something like:
for (x=1; x<items; x++)
{
A1= sum(Item[0]..Item[x-1])
for (y=x; y<items; y++)
{
A2= sum(Item[x]..Item[y-1])
calc f, if new minimum found -keep x,y
}
}
find sum and cumulative sum of series.
get a= sum/3
then locate nearest a, 2*a in the cumulative sum which divides your list into three equal parts.
Lets say p is your array of paragraph heights;
int len= p.sum()/3; //it is avarage value
int currlen=0;
int templen=0;
int indexes[2];
int j = 0;
for (i=0;i<p.lenght;i++)
{
currlen = currlen + p[i];
if (currlen>len)
{
if ((currlen-len)<(abs((currlen-p[i])-len))
{ //check which one is closer to avarege val
indexes[j++] = i;
len=(p.sum()-currlen)/2 //optional: count new avearege height from remaining lengths
currlen = 0;
}
else
{
indexes[j++] = i-1;
len=(p.sum()-currlen)/2
currlen = p[i];
}
}
if (j>2)
break;
}
You will get starting index of 2nd and 3rd sequence. Note its kind of pseudo code :)
I believe that this can be solved with a dynamic programming algorithm for line breaking invented by Donald Knuth for use in TeX.
Following Aasmund Eldhuset answer, I previously answerd this question on SO.
Word wrap to X lines instead of maximum width (Least raggedness)
This algo doesn't rely on the max line size but just gives an optimal cut.
I modified it to work with your problem :
L=[1,5,7,13,3,3,4,1,8,6,6,6]
def minragged(words, n=3):
P=2
cumwordwidth = [0]
# cumwordwidth[-1] is the last element
for word in words:
cumwordwidth.append(cumwordwidth[-1] + word)
totalwidth = cumwordwidth[-1] + len(words) - 1 # len(words) - 1 spaces
linewidth = float(totalwidth - (n - 1)) / float(n) # n - 1 line breaks
print "number of words:", len(words)
def cost(i, j):
"""
cost of a line words[i], ..., words[j - 1] (words[i:j])
"""
actuallinewidth = max(j - i - 1, 0) + (cumwordwidth[j] - cumwordwidth[i])
return (linewidth - float(actuallinewidth)) ** P
"""
printing the reasoning and reversing the return list
"""
F={} # Total cost function
for stage in range(n):
print "------------------------------------"
print "stage :",stage
print "------------------------------------"
print "word i to j in line",stage,"\t\tTotalCost (f(j))"
print "------------------------------------"
if stage==0:
F[stage]=[]
i=0
for j in range(i,len(words)+1):
print "i=",i,"j=",j,"\t\t\t",cost(i,j)
F[stage].append([cost(i,j),0])
elif stage==(n-1):
F[stage]=[[float('inf'),0] for i in range(len(words)+1)]
for i in range(len(words)+1):
j=len(words)
if F[stage-1][i][0]+cost(i,j)<F[stage][j][0]: #calculating min cost (cf f formula)
F[stage][j][0]=F[stage-1][i][0]+cost(i,j)
F[stage][j][1]=i
print "i=",i,"j=",j,"\t\t\t",F[stage][j][0]
else:
F[stage]=[[float('inf'),0] for i in range(len(words)+1)]
for i in range(len(words)+1):
for j in range(i,len(words)+1):
if F[stage-1][i][0]+cost(i,j)<F[stage][j][0]:
F[stage][j][0]=F[stage-1][i][0]+cost(i,j)
F[stage][j][1]=i
print "i=",i,"j=",j,"\t\t\t",F[stage][j][0]
print 'reversing list'
print "------------------------------------"
listWords=[]
a=len(words)
for k in xrange(n-1,0,-1):#reverse loop from n-1 to 1
listWords.append(words[F[k][a][1]:a])
a=F[k][a][1]
listWords.append(words[0:a])
listWords.reverse()
for line in listWords:
print line, '\t\t',sum(line)
return listWords
THe result I get is :
[1, 5, 7, 13] 26
[3, 3, 4, 1, 8] 19
[6, 6, 6] 18
[[1, 5, 7, 13], [3, 3, 4, 1, 8], [6, 6, 6]]
Hope it helps

Resources