Discussion about how to retrieve an i-th element in the j-th level of a binary tree algorithm - algorithm

I am solving some problems from a site called codefights and the last one solved was about a binary tree in which are:
Consider a special family of Engineers and Doctors. This family has
the following rules:
Everybody has two children. The first child of an Engineer is an
Engineer and the second child is a Doctor. The first child of a Doctor
is a Doctor and the second child is an Engineer. All generations of
Doctors and Engineers start with an Engineer.
We can represent the situation using this diagram:
E
/ \
E D
/ \ / \
E D D E
/ \ / \ / \ / \
E D D E D E E D
Given the level and position of a person in the ancestor tree above,
find the profession of the person. Note: in this tree first child is
considered as left child, second - as right.
As there is some space and time restrictions, the solution can not be based on actually constructing the tree until the level required and check which element is in the position asked. So far so good. My proposed solution written in python was:
def findProfession(level, pos):
size = 2**(level-1)
shift = False
while size > 2:
if pos <= size/2:
size /= 2
else:
size /= 2
pos -= size
shift = not shift
if pos == 1 and shift == False:
return 'Engineer'
if pos == 1 and shift == True:
return 'Doctor'
if pos == 2 and shift == False:
return 'Doctor'
if pos == 2 and shift == True:
return 'Engineer'
As it solved the problem, I got access to the solutions of other used and I was astonished by this one:
def findProfession(level, pos):
return ['Engineer', 'Doctor'][bin(pos-1).count("1")%2]
Even more, I did not understand the logic behind it and so we arrived to this question. Someone could explain to me this algorithm?

Let's number the nodes of the tree in the following way:
1) the root has number 1
2) the first child of node x has number 2*x
3) the second child of node x has number 2*x+1
Now, notice that each time you go to the first child, the profession stays the same, and you add a 0 to the binary representation of the node.
And each time you go to the second child, the profession flips and you add a 1 to the binary representation.
Example: Let's find the profession of the 4th node in the 4th level (last level in the diagram you have in the question). First we start at the root with number 1, then we go to the first child with number 2 (10 binary). After that we go to the second child of 2 which is 5 (101 binary). Finally, we go to the second child of 5 which is 11 (1011 binary).
Notice that we started with only one bit equal to 1, then every 1 bit we added to the binary representation flipped the profession. So the number of times we flip a profession is equal to the (number of bits equal to 1) - 1. The parity of this amount decides the profession.
This leads us to the following solution:
X = number of bits equal to 1 in [ 2^(level-1) + pos - 1 ]
Y = (X-1) mod 2
if Y is 0 then the answer is "Engineer"
Otherwise the answer is "Doctor"
since 2^(level-1) is a power of 2, it has exactly one bit equal to 1, therefore you can write:
X = number of bits equal to 1 in [ pos-1 ]
Y = X mod 2
Which is equal to the solution you mentioned in the question.

This type of sequence is known as the Thue-Morse sequence. Using the same tree, here is a demonstration of why it gives the correct answer:
p is the 0-indexed position
b is the binary representation of p
c is the number of 1's in b
p0
E
b0
c0
/ \
p0 p1
E D
b0 b1
c0 c1
/ \ / \
p0 p1 p2 p3
E D D E
b0 b1 b10 b11
c0 c1 c1 c2
/ \ / \ / \ / \
p0 p1 p2 p3 p4 p5 p6 p7
E D D E D E E D
b0 b1 b10 b11 b100 b101 b110 b111
c0 c1 c1 c2 c1 c2 c2 c3
c is always even for Engineer and odd for Doctor. Therefore:
index = bin(pos-1).count('1') % 2
return ['Engineer', 'Doctor'][index]

Related

2D Matrix Problem - how many people can get a color that they want?

Given a bitarray such as the following:
C0 C1 C2 C3 C4 C5
**********************************************
P0 * 0 0 1 0 1 0 *
P1 * 0 1 0 0 1 0 *
P2 * 0 0 0 1 1 0 *
P3 * 1 0 0 0 0 1 *
P4 * 0 0 0 0 0 0 *
P5 * 0 0 0 0 0 0 *
P6 * 1 0 0 0 0 0 *
**********************************************
Each row represents a different person P_i, while each column represent a different color C_j. If a given cell A[i][j] is 1, it means that person i would like color j. A person can only get one color, and a color can only be given to one person.
In general, the number of people P > 0, and the number of colors C >= 0.
How can I, time-efficiently, compute the maximal amount of people who can get a color that they want?
The correct answer to the example above would be 5.
Person 6 (P6) only has one wish, so he gets color 0 (C0)
Since C0 is now taken, P3 only has one wish left, so he gets C5.
P0 gets C2, P1 gets C1 and P2 gets C3.
My first idea was a greedy algorithm, that simply favored the person (i.e. row) with the lowest amount of wanted colors. This works for the most part, but is simply too slow for my liking, as it runs in O(P*(P*C)) time, which is equal to O(n^3) when n = P = C. Any ideas to an algorithm (or another data structure) that can solve the problem quicker?
This might be a duplicate of another similar question, but I had trouble with finding the correct name for the type of problem, so bear with me if this is the case.
This is a classical problem known as maximum cardinality bipartite matching . Here, you have a bipartite graph where in one side you have the vertices corresponding to the people and on the other side the vertices corresponding to the colors. An edge between a person and a color exists if there is a one in the corresponding entry in the matrix.
In the general case, the best known algorithms has worst case performance O(E*sqrt(V)), where E is the number of edges in the graph and V is the number of vertices. One such algorithm is called Hopcroft-Karp. I would suggest you to read the Wikipedia explanation that I linked.

A feature ranking algorithm

if I have the following partitions or subsets with the corresponding scores as follows:
{X1,X2} with score C1
{X2,X3} with score C2
{X3,X4} with score C3
{X4,X1} with score C4
I want to write an algorithm that will rank the Xs based on the corresponding score of the subset they appeared in.
one way for example will be to do the following:
X1 = (C1 + C4)/2
X2 = (C1 + C2)/2
X3 = (C2 + C3)/2
X4 = (C3 + C4)/2
and then sort the results.
is there a more efficient or better ideas to do the ranking?
If you think that the score of a set is the sum of the scores of each object, you can write your equation in matrix form as :
C = M * X
where C is a vector of length 4 with components C1, C2, C3, C4, M is the matrix (in your case, as I understand this may vary)
1 1 0 0
0 1 1 0
0 0 1 1
1 0 0 1
and X is the unknown. You can then use Gaussian elimination to determine X and the get the ranking as you suggested.

Looking for a generic, fast, low-memory algorithm to output N-out-of-M combinations of an array without repetitions

I have an array with players
$players = array('A','B','C','D','E','F');
and i want to get every possible 3 way finishing.
1st 2nd 3rd
A B C
A B D
...
C A B
C B A
...
F D E
F E D
I have some permutation algorithm but it must be something else since in permutation there is 6 * 5 * 4 * 3 * 2 * 1 combination and here is only 6 * 5 * 4
Here's some pseudo-code to print your 3 out of 6 combinations without repetition:
for i = 1 to 6
for j = 1 to 6
if (j != i)
for k = 1 to 6
if (k != i && k != j)
print(A[i], A[j], A[k])
end if
next k
end if
next j
next i
For the general k-of-n case see: Algorithm to return all combinations of k elements from n
Given your permutation algorithm, you can use it in two steps to get the desired permutations.
First, let's consider the following mapping. Given input as A1 A2 A3 A4 A5 ... An, a value b1 b2 b3 b4 b5 ... bn means select Ai if bi is 1 and not if it is 0.
With your input, for example:
0 0 1 1 0 1 -> C D F
0 1 0 0 1 1 -> B E F
Now your algorithm can go as follows:
Take n as the number of elements (in your case 6) and m as the number you want to choose from.
Construct the following sequence:
0 0 0 ... 0 1 1 1 ... 1
\____ ____/ \____ ____/
V V
n - m m
Get all permutations of the above sequence and for each:
Find the m elements that are marked in the sequence
Get all permutations of those m elements and for each:
do whatever you want!
Your problem is not finding all permutations of 6 elements.
Your problem is to choose 3 elements, and than check its permutations.
The number of combinations = C(6,3)*3! = 6! / 3! = 6*5*4.
C(6,3) - for choosing 3 elements out of 6. (No matter the order)
3! - for ordering the 3 chosen elements.
This is the exactly number of combinations you should get. (and you do)
However, you can use your permutation algorithm to get all permutations of the 6 elements.
Than, just ignore the last 3 elements, and remove duplicates from the result.
I may be wrong but I think you have the correct amount of possible permutations here. You choose only 3 players among the 6 players array. So for the first player, you have 6 possibilities, for the second player you have 5 possibilities, and for the third player, you have 4 possibilities.
If you decide to have 4 players at the end instead of having 3, the possible amount of permutations would be 6*5*4*3, and so on.
I hope my math is not too old!

How to decompose an integer in two for grid creation

Given an integer N I want to find two integers A and B that satisfy A × B ≥ N with the following conditions:
The difference between A × B and N is as low as possible.
The difference between A and B is as low as possible (to approach a square).
Example: 23. Possible solutions 3 × 8, 6 × 4, 5 × 5. 6 × 4 is the best since it leaves just one empty space in the grid and is "less" rectangular than 3 × 8.
Another example: 21. Solutions 3 × 7 and 4 × 6. 3 × 7 is the desired one.
A brute force solution is easy. I would like to see if a clever solution is possible.
Easy.
In pseudocode
a = b = floor(sqrt(N))
if (a * b >= N) return (a, b)
a += 1
if (a * b >= N) return (a, b)
return (a, b+1)
and it will always terminate, the distance between a and b at most only 1.
It will be much harder if you relax second constraint, but that's another question.
Edit: as it seems that the first condition is more important, you have to attack the problem
a bit differently. You have to specify some method to measure the badness of not being square enough = 2nd condition, because even prime numbers can be factorized as 1*number, and we fulfill the first condition. Assume we have a badness function (say a >= b && a <= 2 * b), then factorize N and try different combinations to find best one. If there aren't any good enough, try with N+1 and so on.
Edit2: after thinking a bit more I come with this solution, in Python:
from math import sqrt
def isok(a, b):
"""accept difference of five - 2nd rule"""
return a <= b + 5
def improve(a, b, N):
"""improve result:
if a == b:
(a+1)*(b-1) = a^2 - 1 < a*a
otherwise (a - 1 >= b as a is always larger)
(a+1)*(b-1) = a*b - a + b - 1 =< a*b
On each iteration new a*b will be less,
continue until we can, or 2nd condition is still met
"""
while (a+1) * (b-1) >= N and isok(a+1, b-1):
a, b = a + 1, b - 1
return (a, b)
def decomposite(N):
a = int(sqrt(N))
b = a
# N is square, result is ok
if a * b >= N:
return (a, b)
a += 1
if a * b >= N:
return improve(a, b, N)
return improve(a, b+1, N)
def test(N):
(a, b) = decomposite(N)
print "%d decomposed as %d * %d = %d" % (N, a, b, a*b)
[test(x) for x in [99, 100, 101, 20, 21, 22, 23]]
which outputs
99 decomposed as 11 * 9 = 99
100 decomposed as 10 * 10 = 100
101 decomposed as 13 * 8 = 104
20 decomposed as 5 * 4 = 20
21 decomposed as 7 * 3 = 21
22 decomposed as 6 * 4 = 24
23 decomposed as 6 * 4 = 24
I think this may work (your conditions are somewhat ambiguous). this solution is somewhat similar to other one, in basically produces rectangular matrix which is almost square.
you may need to prove that A+2 is not optimal condition
A0 = B0 = ceil (sqrt N)
A1 = A0+1
B1 = B0-1
if A0*B0-N > A1*B1-N: return (A1,B1)
return (A0,B0)
this is solution if first condition is dominant (and second condition is not used)
A0 = B0 = ceil (sqrt N)
if A0*B0==N: return (A0,B0)
return (N,1)
Other conditions variations will be in between
A = B = ceil (sqrt N)

CodeGolf: Brothers

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I just finished participating in the 2009 ACM ICPC Programming Conest in the Latinamerican Finals. These questions were for Brazil, Bolivia, Chile, etc.
My team and I could only finish two questions out of the eleven (not bad I think for the first try).
Here's one we could finish. I'm curious to seeing any variations to the code. The question in full: ps: These questions can also be found on the official ICPC website available to everyone.
In the land of ACM ruled a greeat king who became obsessed with order. The kingdom had a rectangular form, and the king divided the territory into a grid of small rectangular counties. Before dying the king distributed the counties among his sons.
The king was unaware of the rivalries between his sons: The first heir hated the second but not the rest, the second hated the third but not the rest, and so on...Finally, the last heir hated the first heir, but not the other heirs.
As soon as the king died, the strange rivaly among the King's sons sparked off a generalized war in the kingdom. Attacks only took place between pairs of adjacent counties (adjacent counties are those that share one vertical or horizontal border). A county X attacked an adjacent county Y whenever X hated Y. The attacked county was always conquered. All attacks where carried out simultanously and a set of simultanous attacks was called a battle. After a certain number of battles, the surviving sons made a truce and never battled again.
For example if the king had three sons, named 0, 1 and 2, the figure below shows what happens in the first battle for a given initial land distribution:
INPUT
The input contains several test cases. The first line of a test case contains four integers, N, R, C and K.
N - The number of heirs (2 <= N <= 100)
R and C - The dimensions of the land. (2 <= R,C <= 100)
K - Number of battles that are going to take place. (1 <= K <= 100)
Heirs are identified by sequential integers starting from zero. Each of the next R lines contains C integers HeirIdentificationNumber (saying what heir owns this land) separated by single spaces. This is to layout the initial land.
The last test case is a line separated by four zeroes separated by single spaces. (To exit the program so to speak)
Output
For each test case your program must print R lines with C integers each, separated by single spaces in the same format as the input, representing the land distribution after all battles.
Sample Input: Sample Output:
3 4 4 3 2 2 2 0
0 1 2 0 2 1 0 1
1 0 2 0 2 2 2 0
0 1 2 0 0 2 0 0
0 1 2 2
Another example:
Sample Input: Sample Output:
4 2 3 4 1 0 3
1 0 3 2 1 2
2 1 2
Perl, 233 char
{$_=<>;($~,$R,$C,$K)=split;if($~){#A=map{$_=<>;split}1..$R;$x=0,
#A=map{$r=0;for$d(-$C,$C,1,-1){$r|=($y=$x+$d)>=0&$y<#A&1==($_-$A[$y])%$~
if($p=(1+$x)%$C)>1||1-$d-2*$p}$x++;($_-$r)%$~}#A
while$K--;print"#a\n"while#a=splice#A,0,$C;redo}}
The map is held in a one-dimensional array. This is less elegant than the two-dimensional solution, but it is also shorter. Contains the idiom #A=map{...}#A where all the fighting goes on inside the braces.
Python (420 characters)
I haven't played with code golf puzzles in a while, so I'm sure I missed a few things:
import sys
H,R,C,B=map(int,raw_input().split())
M=(1,0), (0,1),(-1, 0),(0,-1)
l=[map(int,r.split())for r in sys.stdin]
n=[r[:]for r in l[:]]
def D(r,c):
x=l[r][c]
a=[l[r+mr][c+mc]for mr,mc in M if 0<=r+mr<R and 0<=c+mc<C]
if x==0and H-1in a:n[r][c]=H-1
elif x-1in a:n[r][c]=x-1
else:n[r][c]=x
G=range
for i in G(B):
for r in G(R):
for c in G(C):D(r,c)
l=[r[:] for r in n[:]]
for r in l:print' '.join(map(str,r))
Lua, 291 Characters
g=loadstring("return io.read('*n')")repeat n=g()r=g()c=g()k=g()l={}c=c+1 for
i=0,k do w={}for x=1,r*c do a=l[x]and(l[x]+n-1)%n w[x]=i==0 and x%c~=0 and
g()or(l[x-1]==a or l[x+1]==a or l[x+c]==a or l[x-c]==a)and a or
l[x]io.write(i~=k and""or x%c==0 and"\n"or w[x].." ")end l=w end until n==0
F#, 675 chars
let R()=System.Console.ReadLine().Split([|' '|])|>Array.map int
let B(a:int[][]) r c g=
let n=Array.init r (fun i->Array.copy a.[i])
for i in 1..r-2 do for j in 1..c-2 do
let e=a.[i].[j]-1
let e=if -1=e then g else e
if a.[i-1].[j]=e||a.[i+1].[j]=e||a.[i].[j-1]=e||a.[i].[j+1]=e then
n.[i].[j]<-e
n
let mutable n,r,c,k=0,0,0,0
while(n,r,c,k)<>(0,2,2,0)do
let i=R()
n<-i.[0]
r<-i.[1]+2
c<-i.[2]+2
k<-i.[3]
let mutable a=Array.init r (fun i->
if i=0||i=r-1 then Array.create c -2 else[|yield -2;yield!R();yield -2|])
for j in 1..k do a<-B a r c (n-1)
for i in 1..r-2 do
for j in 1..c-2 do
printf "%d" a.[i].[j]
printfn ""
Make the array big enough to put an extra border of "-2" around the outside - this way can look left/up/right/down without worrying about out-of-bounds exceptions.
B() is the battle function; it clones the array-of-arrays and computes the next layout. For each square, see if up/down/left/right is the guy who hates you (enemy 'e'), if so, he takes you over.
The main while loop just reads input, runs k iterations of battle, and prints output as per the spec.
Input:
3 4 4 3
0 1 2 0
1 0 2 0
0 1 2 0
0 1 2 2
4 2 3 4
1 0 3
2 1 2
0 0 0 0
Output:
2220
2101
2220
0200
103
212
Python 2.6, 383 376 Characters
This code is inspired by Steve Losh' answer:
import sys
A=range
l=lambda:map(int,raw_input().split())
def x(N,R,C,K):
if not N:return
m=[l()for _ in A(R)];n=[r[:]for r in m]
def u(r,c):z=m[r][c];n[r][c]=(z-((z-1)%N in[m[r+s][c+d]for s,d in(-1,0),(1,0),(0,-1),(0,1)if 0<=r+s<R and 0<=c+d<C]))%N
for i in A(K):[u(r,c)for r in A(R)for c in A(C)];m=[r[:]for r in n]
for r in m:print' '.join(map(str,r))
x(*l())
x(*l())
Haskell (GHC 6.8.2), 570 446 415 413 388 Characters
Minimized:
import Monad
import Array
import List
f=map
d=getLine>>=return.f read.words
h m k=k//(f(\(a#(i,j),e)->(a,maybe e id(find(==mod(e-1)m)$f(k!)$filter(inRange$bounds k)[(i-1,j),(i+1,j),(i,j-1),(i,j+1)])))$assocs k)
main=do[n,r,c,k]<-d;when(n>0)$do g<-mapM(const d)[1..r];mapM_(\i->putStrLn$unwords$take c$drop(i*c)$f show$elems$(iterate(h n)$listArray((1,1),(r,c))$concat g)!!k)[0..r-1];main
The code above is based on the (hopefully readable) version below. Perhaps the most significant difference with sth's answer is that this code uses Data.Array.IArray instead of nested lists.
import Control.Monad
import Data.Array.IArray
import Data.List
type Index = (Int, Int)
type Heir = Int
type Kingdom = Array Index Heir
-- Given the dimensions of a kingdom and a county, return its neighbors.
neighbors :: (Index, Index) -> Index -> [Index]
neighbors dim (i, j) =
filter (inRange dim) [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]
-- Given the first non-Heir and a Kingdom, calculate the next iteration.
iter :: Heir -> Kingdom -> Kingdom
iter m k = k // (
map (\(i, e) -> (i, maybe e id (find (== mod (e - 1) m) $
map (k !) $ neighbors (bounds k) i))) $
assocs k)
-- Read a line integers from stdin.
readLine :: IO [Int]
readLine = getLine >>= return . map read . words
-- Print the given kingdom, assuming the specified number of rows and columns.
printKingdom :: Int -> Int -> Kingdom -> IO ()
printKingdom r c k =
mapM_ (\i -> putStrLn $ unwords $ take c $ drop (i * c) $ map show $ elems k)
[0..r-1]
main :: IO ()
main = do
[n, r, c, k] <- readLine -- read number of heirs, rows, columns and iters
when (n > 0) $ do -- observe that 0 heirs implies [0, 0, 0, 0]
g <- sequence $ replicate r readLine -- read initial state of the kingdom
printKingdom r c $ -- print kingdom after k iterations
(iterate (iter n) $ listArray ((1, 1), (r, c)) $ concat g) !! k
main -- handle next test case
AWK - 245
A bit late, but nonetheless... Data in a 1-D array. Using a 2-D array the solution is about 30 chars longer.
NR<2{N=$1;R=$2;C=$3;K=$4;M=0}NR>1{for(i=0;i++<NF;)X[M++]=$i}END{for(k=0;k++<K;){
for(i=0;i<M;){Y[i++]=X[i-(i%C>0)]-(b=(N-1+X[i])%N)&&X[i+((i+1)%C>0)]-b&&X[i-C]-b
&&[i+C]-b?X[i]:b}for(i in Y)X[i]=Y[i]}for(i=0;i<M;)printf"%s%d",i%C?" ":"\n",
X[i++]}

Resources