Better solution than the naive O(n*log(n)) approach - algorithm

you are given a string consisting of only 1's. eg: "11111111"
you have an iterator that changes direction when it hits the extremes of the string. starting in the direction left to right.
the iterator replaces the next immediate '1' in its path with a zero and then skips to the '1' following that. This goes on until there is only one '1' remaining in the string.
you have to print the location of that '1'.
here is a python 3 code with the naive solution (it also prints the steps for understanding the problem, although steps are not required for the expected answer):
n=int(input("enter the number of people in the row : "))
assert(n>=1)
input_string="1"*n
print(input_string)
direction=1
iterator=0
count=0
while(count!=1):
count=0
next_to_delete=-1
while(iterator<len(input_string) and iterator>=0):
if(input_string[iterator]=='1'):
if(next_to_delete==-1):
next_to_delete=iterator
else:
input_string=input_string[:iterator]+"0"+input_string[iterator+1:]
#i.e. input_string[iterator]='0'
next_to_delete=-1
count+=1
iterator+=direction
print(input_string)
direction=1 if direction==-1 else -1
iterator+=direction
print("answer is : ",end='')
print(next_to_delete+1)
example:
if n=4::::::::::
1111
1010
0010
answer is : 3
if n=5::::::::::
11111
10101
10001
10000
answer is : 1

Here is a log(n) solution:
def survivor_number(n):
if n % 2 == 0:
n -= 1
b = 2
t = 1
while b <= n:
t += b & n
b *= 4
return t
This is based on the algorithm in OEIS for sequence A090569

Related

Find Missing row in n*2^n matrix in 2^n time Algorithm question

I encountered an Algorithms question which seemed easy at first but I'm puzzled and don't know what to do! the question is as follows:
Suppose we have a number n, and then we have a matrix of n columns and 2*n rows. it is like the power set (e.g. for n=2 we have 10,11,00,01). the rows don't necessarily follow any order. also we can access each matrix member in O(1) time. now, we have (2^n)-1 of the rows, and we want to find the last row in least possible time (note that there are n*(2^n-1) members and we only have O(2^n) time). how can we do this? (we have O(n) memory. though I'm not sure if it's enough. if you know an answer which uses any amount of memory it's fine)
Example input:
3
101
110
100
000
111
011
010
Example output: 001
I tried to model it by the popular missing bit problem (by xor-ing the matrix members) but couldn't do much progress.
P.S. an implementation of the algorithm on C/C++/Java/Python will be very appreciated as it clarifies things up.
P.S.S: Can you also cite some sources? or tell me how you came up with the answer and how you think about such questions?
The constraints are a little vague, but you're probably looking for something like this:
Check the first item in all 2^n rows to determine the first item in the missing row. Either 1 or zero will start 2^(n-1) rows, and the other option will start 2^(n-1)-1 rows -- item with the lower count starts the missing row.
Check the second item in the 2^(n-1)-1 rows that start with the same item as the missing row, to find the second item in the missing row.
Continue to find all n items in the missing row.
If you sum up the number of elements read you get 2^n + 2^(n-1) + 2^(n-2) ... which is less than 2^(n+1) and therefore in O(2^n)
You have 2 cases here:
Degenerated case: N == 1 which is evident. 0 -> 1 and 1 -> 0; you can, say, put it as ~item
General case N > 1. All you have to do is to xor all the values:
101 ^ 110 ^ 100 ^ 000 ^ 111 ^ 011 ^ 010 == 001
the algorithm has O(N * 2**N) time complexity (we have to read each cell of the matrix) and wants O(n) space (to store temporal sum when xoring).
C# implementation (Linq):
string source = "3 101 110 100 000 111 011 010";
// "001"
// new char[] { ' ', '\r', '\n', 't' } - to be on the safe side -
// whatever delimiter is we'll get a correct array
string result = source
.Split(new char[] { ' ', '\r', '\n', 't' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(1) // we don't want "3"
.Aggregate((sum, item) => // xoring strings
string.Concat(sum.Zip(item, (x, y) => (char)((x - '0') ^ (y - '0') + '0'))));
Let's prove algorithm's correctness (N > 1).
Since N > 1 and thus 2**N >= 4 then 2**(N - 1) is some even value. Let's have a look at arbitrary bit of all 2**N items of the power serie
000...0...0
000...0...1
...
111.......0
111...1...1
^
- N/2 '0's (even) and N/2 '1' (even), xor == 0
we find that we have exactly N / 2 zeroes and N / 2 ones; xor of all these bits is aways 0 (since N / 2 == 2**(N - 1) is some even value).
If one line is missed, e.g. 0...1...1 we have 2 possibilities:
Missed bit is 1. So we have N / 2 zeroes and N / 2 - 1 ones; xor of all bits returns 1
Missed bit is 0. So we have N / 2 - 1 zeroes and N / 2 - 1 ones; xor of all bits returns 1
Since ^ is a bitwise operation (value of jth bit doesn't depend on values of ith bits) and we prove that arbitrary bit is correct one the entire value is correct as well.

Longest substring where every character appear even number of times (possibly zero)

Suppose we have a string s. We want to find the length of the longest substring of s such that every character in the substring appears even number of times (possible zero).
WC Time: O(nlgn). WC space: O(n)
First, it's obvious that the substring must be of an even length. Second, I'm familiar with the sliding window method where we anchor some right index and look for the left-most index to match your criterion. I tried to apply this idea here but couldn't really formulate it.
Also, it seems to me like a priority queue could come in handy (since the O(nlgn) requirement is sort of hinting it)
I'd be glad for help!
Let's define the following bitsets:
B[c,i] = 1 if character c appeared in s[0,...,i] even number of times.
Calculating B[c,i] takes linear time (for all values):
for all c:
B[c,-1] = 0
for i from 0 to len(arr):
B[c, i] = B[s[i], i-1] XOR 1
Since the alphabet is of constant size, so are the bitsets (for each i).
Note that the condition:
every character in the substring appears even number of times
is true for substring s[i,j] if and only if the bitset of index i is identical to the bitset of index j (otherwise, there is a bit that repeated odd number of times in this substring ; other direction: If there is a bit that repeated number of times, then its bit cannot be identical).
So, if we store all bitsets in some set (hash set/tree set), and keep only latest entry, this preprocessing takes O(n) or O(nlogn) time (depending on hash/tree set).
In a second iteration, for each index, find the farther away index with identical bitset (O(1)/O(logn), depending if hash/tree set), find the substring length, and mark it as candidate. At the end, take the longest candidate.
This solution is O(n) space for the bitsets, and O(n)/O(nlogn) time, depending if using hash/tree solution.
Pseudo code:
def NextBitset(B, c): # O(1) time
for each x in alphabet \ {c}:
B[x, i] = B[x, i-1]
B[c, i] = B[c, i-1] XOR 1
for each c in alphabet: # O(1) time
B[c,-1] = 0
map = new hash/tree map (bitset->int)
# first pass: # O(n)/O(nlogn) time
for i from 0 to len(s):
# Note, we override with the latest element.
B = NextBitset(B, s[i])
map[B] = i
for each c in alphabet: # O(1) time
B[c,-1] = 0
max_distance = 0
# second pass: O(n)/ O(nlogn) time.
for i from 0 to len(s):
B = NextBitset(B, s[i])
j = map.find(B) # O(1) / O(logn)
max_distance = max(max_distance, j-i)
I'm not sure exactly what amit proposes so if this is it, please consider it another explanation. This can be accomplished in a single traversal.
Produce a bitset of length equal to the alphabet's for each index of the string. Store the first index for each unique bitset encountered while traversing the string. Update the largest interval between a current and previously seen bitset.
For example, the string, "aabccab":
a a b c c a b
0 1 2 3 4 5 6 (index)
_
0 1 0 0 0 0 1 1 | (vertical)
0 0 0 1 1 1 1 0 | bitset for
0 0 0 0 1 0 0 0 _| each index
^ ^
|___________|
largest interval
between current and
previously seen bitset
The update for each iteration can be accomplished in O(1) by preprocessing a bit mask for each character to XOR with the previous bitset:
bitset mask
0 1 1
1 XOR 0 = 1
0 0 0
means update the character associated with the first bit in the alphabet-bitset.

Cannot understand an answer to an algorithm

I was doing this question today.
Basically, question asks for the largest 'Decent' Number having N digits where 'Decent' number is:
Only 3 and 5 as its digits.
Number of times 3 appears is divisible by 5.
Number of times 5 appears is divisible by 3.
Input Format
The 1st line will contain an integer T, the number of test cases,
followed by T lines, each line containing an integer N i.e. the number
of digits in the number
Output Format
Largest Decent number having N digits. If no such number exists, tell
Sherlock that he is wrong and print '-1'
Sample Input
4
1
3
5
11
Sample Output
-1
555
33333
55555533333
Explanation
For N=1 , there is no such number. For N=3, 555 is only possible
number. For N=5, 33333 is only possible number. For N=11 , 55555533333
and all of permutations of digits are valid numbers, among them, the
given number is the largest one.
I've solved it using normal method but saw this answer:
t = int(raw_input())
for _ in range(t):
n = int(raw_input())
c3 = 5*(2*n%3)
if c3 > n:
print -1
else:
print '5' * (n-c3) + '3'*c3
Can anyone explain the method please? Especially the line 'c3 = 5*(2*n%3)', thanks
We are looking for integer solutions of n = 5*x + 3*y where 5*x is the number of 3s and 3*y is the number of 5s. Both x and y must be >= 0 and x should be as small as possible since we can build larger numbers if we have more 5s.
Transforming this gives y = (n-5*x)/3. In order for y to be an integer n-5*x must be a multiple of 3 so we can calculate modulo 3 (I write == for is congruent modulo 3 from now on).
n-5*x == 0
n == 5*x == 2*x (because 5 == 2)
multiplying both sides by 2 gives
2*n == 4*x == x (because 4 == 1)
Since we want x small we take x = 2 * n % 3 and y = (n-5*x)/3
There is no solution if y < 0.

Is there an infinite loop in my code for solving Collatz sequence?

My code is trying to find the answer to this problem: The following iterative sequence is defined for the set of positive integers:
n → n/2 (n is even)
n → 3n + 1 (n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.
And here is my code:
step_count = 1
score = {}
largest_score = 1
(1..1000000).map do |n|
while n >= 1 do
if n%2 == 0 then
n/2
step_count += 1
else
(3*n)+1
step_count += 1
end
end
score = {n => step_count}
end
score.each {|n, step_count| largest_score = step_count if largest_score < step_count}
puts score.key(largest_score)
I ran it for over an hour and still no answer. Is there an infinite loop in my code, or maybe some different problem, and if so what is it?
I am using Ruby 1.8.7
Yes, you've got an infinite loop. It's here:
while n >= 1 do
if n%2 == 0 then
n/2
step_count += 1
else
(3*n)+1
step_count += 1
end
end
The condition in your while loop is testing n, but nothing within the loop is changing its value. What you probably meant to do is this:
while n >= 1 do
if n % 2 == 0
n = n / 2
step_count += 1
else
n = (3 * n) + 1
step_count += 1
end
end
A few sidenotes:
It looks like you mean to be updating the score hash with new key-value pairs, but as written, score = { n => step_count } will replace it entirely on each iteration. To add new pairs to the existing Hash, use score[n] = step_count.
It's much more efficient to look up a value in a Hash by its key than the other way around, so you might want to reverse your Hash storage: score[step_count] = n, finding the largest score with score.each { |step_count, n| #... and reading it out with score[largest_score]. This has the added advantage that you won't have to store all million results; it'll only store the last number you reach that results in a chain of a given length. Of course, it also means that you'll only see one number that results in the largest chain, even if there are multiple numbers that have the same, highest chain length! The problem is worded as though the answer is unique, but if it isn't, you won't find out.
To debug problems like this in the future, it's handy to drop your loop iterations to something tiny (ten, say) and sprinkle some puts statements within your loops to watch what's happening and get a feel for the execution flow.
Try the following solution for your problem:
def solve(n)
max_collatz = 0; max_steps = 0
(1..n).each do |k|
next if k % 2 == 0
next if k % 3 != 1
steps = collatz_sequence_count(k)
if steps > max_steps
max_steps = steps
max_collatz = k
end
end
max_collatz
# answer: 837799 with 525 steps, in nearly 2.2 seconds on my machine
end
def collatz_sequence_count(k)
counter = 1
while true
return counter if k == 1
k = k % 2 == 0 ? k/2 : 3 * k + 1
counter += 1
end
end
# You can then use the above methods to get your answer, like this:
answer = solve 1000000
puts "answer is: #{answer}"
Results (uses a custom home-brewed gem to solve ProjectEuler problems):
nikhgupta at MacBookPro in ~/Code/git/ProjectEuler [ master: ✗ ] 48d
± time euler solve 14 +next: 2 | total: 22 | ▸▸▸▹▹▹▹▹▹▹
0014 | Longest Collatz sequence | It took me: 2.166033 seconds. | Solution: 837799
euler solve 14 3.30s user 0.13s system 99% cpu 3.454 total

Fastest algorithm of getting precise answer (not approximated) when square-rooting

Sorry for unclear title, but I don't know how to state it properly (feel free to edit), so I will give example:
sqrt(108) ~ 10.39... BUT I want it to be like this sqrt(108)=6*sqrt(3) so it means expanding into two numbers
So that's my algorithm
i = floor(sqrt(number)) //just in case, floor returns lowest integer value :)
while (i > 0) //in given example number 108
if (number mod (i*i) == 0)
first = i //in given example first is 6
second = number / (i*i) //in given example second is 3
i = 0
i--
Maybe you know better algorithm?
If it matters I will use PHP and of course I will use appropriate syntax
There is no fast algorithm for this. It requires you to find all the square factors. This requires at least some factorizing.
But you can speed up your approach by quite a bit. For a start, you only need to find prime factors up to the cube root of n, and then test whether n itself is a perfect square using the advice from Fastest way to determine if an integer's square root is an integer.
Next speed up, work from the bottom factors up. Every time you find a prime factor, divide n by it repeatedly, accumulating out the squares. As you reduce the size of n, reduce your limit that you'll go to. This lets you take advantage of the fact that most numbers will be divisible by some small numbers, which quickly reduces the size of the number you have left to factor, and lets you cut off your search sooner.
Next performance improvement, start to become smarter about which numbers you do trial divisions by. For instance special case 2, then only test odd numbers. You've just doubled the speed of your algorithm again.
But be aware that, even with all of these speedups, you're just getting more efficient brute force. It is still brute force, and still won't be fast. (Though it will generally be much, much faster than your current idea.)
Here is some pseudocode to make this clear.
integer_sqrt = 1
remainder = 1
# First we special case 2.
while 0 == number % 4:
integer_sqrt *= 2
number /= 4
if 0 == number / 2:
number /= 2
remainder *= 2
# Now we run through the odd numbers up to the cube root.
# Note that beyond the cube root there is no way to factor this into
# prime * prime * product_of_bigger_factors
limit = floor(cube_root(number + 1))
i = 3
while i <= limit:
if 0 == number % i:
while 0 == number % (i*i):
integer_sqrt *= i
number /= i*i
if 0 == number % (i*i):
number /= i
remainder *= i
limit = floor(cube_root(number + 1))
i += 2
# And finally check whether we landed on the square of a prime.
possible_sqrt = floor(sqrt(number + 1))
if number == possible_sqrt * possible_sqrt:
integer_sqrt *= possible_sqrt
else:
remainder *= number
# And the answer is now integer_sqrt * sqrt(remainder)
Note that the various +1s are to avoid problems with the imprecision of floating point numbers.
Running through all of the steps of the algorithm for 2700, here is what happens:
number = 2700
integer_sqrt = 1
remainder = 1
enter while loop
number is divisible by 4
integer_sqrt *= 2 # now 2
number /= 4 # now 675
number is not divisible by 4
exit while loop
number is not divisible by 2
limit = floor(cube_root(number + 1)) # now 8
i = 3
enter while loop
i < =limit # 3 < 8
enter while loop
number is divisible by i*i # 9 divides 675
integer_sqrt *= 3 # now 6
number /= 9 # now 75
number is not divisible by i*i # 9 does not divide 75
exit while loop
i divides number # 3 divides 75
number /= 3 # now 25
remainder *= 3 # now 3
limit = floor(cube_root(number + 1)) # now 2
i += 2 # now 5
i is not <= limit # 5 > 2
exit while loop
possible_sqrt = floor(sqrt(number + 1)) # 5
number == possible_sqrt * possible_sqrt # 25 = 5 * 5
integer_sqrt *= possible_sqrt # now 30
# and now answer is integer_sqrt * sqrt(remainder) ie 30 * sqrt(3)
It's unlikely that there is a fast algorithm for this. See https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness especially https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness/16100#16100
List all prime divisors in increasing order e.g. 2700 = 2*2*3*3*3*5*5. This is the slowest step and requires sqrt(N) operations.
Create an accumulator (start with 1). Scan this list. For every pair of numbers, multiply the accumulator by (one of) them. So after scanning the list above, you get 2*3*5.
Accumulator is your multiplier. The rest remains under square root.

Resources