Solution to Project Euler Problem 54

by

 

01 Jul 2009 (Updated )

How many hands did player one win in the game of poker?

euler54
function output = euler54
	% Solves Project Euler Problem 54
	% numandina@gmail.com
	
	%% Storing Hands in Cells
	
	fid = fopen('poker.txt');
	c = textscan(fid,'%c');
	nz = c{1}; % in nz is one column containing all the characters
	
	% we have 1,000 hands for each player, and nz is of length 20,000 characters.
	% this is because each hand for each player will have 10 characters (5
	% cards, which each card given a number and a suit).
	
	% in the next step we will take each hand for each player and store them in
	% cells (take each consecutive 20 characters, split them in half, then
	% store each ten as one hand for one player). check the next loop to see this.
	
	p1 = cell(1e3,1);
	p2 = cell(1e3,1);
	
	c = 0;
	
	for k = 1:2:2e3
		
		c = c + 1;
		
		p1{c} = nz(k*10-9:k*10); % each consecutive 10 characters constitute one hand
		p2{c} = nz(k*10+1:k*10+10);
		
	end
	
	% by now we will have two 1000-element cells (p1,p2), with each of their
	% elements containing one hand for each player (i.e. p1{3} means third hand
	% for player 1, which will be playing against p2{3}).
	
	%% Formatting
	
	s = 0; % number of hands won by player 1
	
	for k = 1:1e3 % go through each of the 1000 hands
		
		h1 = p1{k}; % hand for p1 as column vector
		h2 = p2{k};	% hand for p2
		
		c1 = repmat(' ',5,2); % preallocating a 5x2 matrix for each hand
		c2 = repmat(' ',5,2);
		
		% for the next loop, we already have each hand as 10 consectuve
		% characters (value, suit), so take each consecutive two characters
		% and store them as a row.
		for j = 1:5
			
			c1(j,:) = h1(j*2-1:j*2).'; % reshape each hand as 5x2 matrix
			c2(j,:) = h2(j*2-1:j*2).';
			
		end
		
		% now we will have two hands, c1 and c2, with each having values for
		% first column and suits for second column. Thus begin the calculations
		% for each hand.
		
		%% Main Calculations
		
		[r1,v1] = getrank(c1); % get ranks for both hands, as well as rank values
		[r2,v2] = getrank(c2);
		
		if r1 > r2 % if p1's rank is higher than p2's rank
			
			s = s + 1;
			
		elseif r1 == r2 % if their ranks are equal, compare rank values
			
			if v1 > v2 % if p1's rank value is the highest
				
				s = s + 1;
				
			elseif v1 == v2 % if their values are equal, compare second values, and so on...
				
				if r1 == 7 % for example, if two four of a kinds are equal in value, compare fifth card values
					
					% since four cards of each hand are equal, comparing sums
					% is like comparing fifth card values
					if sum(findv(c1)) > sum(findv(c1))
						
						s = s + 1;
						
					end
					
				elseif r1 == 6 % if two full houses have the same value (for the three of a kind), compare the pair values
					
					% since three card of each hand are equal, and the
					% remaining two cards of each hand constitute a pair, then
					% comparing sums is like comparing pair values
					if sum(findv(c1)) > sum(findv(c1))
						
						s = s + 1;
						
					end
					
				elseif r1 == 5 % if the two hands are full suits, compare second highest card of both hands, if they are equal, compare second highest cards,and so on
					
					tc1 = sort(findv(c1));
					tc2 = sort(findv(c2));
					
					ti = 4;
					
					% keep changing index from second bottom (since bottom is
					% highest and has alread been checked) upward until we find
					% an index where the two hand cards don't have the same value
					while ti > 0 && tc1(ti) == tc2(ti)
						
						ti = ti - 1;
						
					end
					
					if tc1(ti) > tc2(ti)
						
						s = s + 1;
						
					end
					
				elseif r1 == 3 % if both values of three of a kind hands are equal
					
					tc1 = sort(findv(c1));
					tc2 = sort(findv(c2));
					
					% set repeated three cards as 0 for each hand
					tc1(tc1 == v1) = 0;
					tc2(tc2 == v2) = 0;
					
					% if max of remaining cards of hands is different
					if max(tc1) > max(tc2)
						
						s = s + 1;
						
						% else if max of both hands is also equal, check last card
					elseif max(tc1) == max(tc2)
						
						% sums are equivalent to compairing last card values,
						% since all other card values are equal for both hands
						if sum(tc1) > sum(tc2)
							
							s = s + 1;
							
						end
						
					end
					
				elseif r1 == 2 % if values of two two pair hands are equal
					
					tc1 = sort(findv(c1));
					tc2 = sort(findv(c2));
					
					% remove cards of the highest pair in each hand
					tc1(tc1 == v1) = [];
					tc2(tc2 == v2) = [];
					
					% find new value of hand 1 (value of second pair)
					if tc1(1) == tc1(2)
						
						v1n = tc1(1);
						
					else
						
						v1n = tc1(2);
						
					end
					
					% find new value of hand 2 (value of second pair)
					if tc2(1) == tc2(2)
						
						v2n = tc2(1);
						
					else
						
						v2n = tc2(2);
						
					end
					
					% compare new values
					if v1n > v2n
						
						s = s + 1;
						
						% if new values are equal too
					elseif v1n == v2n
						
						% remove the second pair from both hands
						tc1(tc1 == v1n) = [];
						tc2(tc2 == v2n) = [];
						
						% now we are left with one card for each hand
						if tc1 > tc2
							
							s = s + 1;
							
						end
						
					end
					
				elseif r1 == 1 % if two one pair hands are equal in value
					
					tc1 = sort(findv(c1));
					tc2 = sort(findv(c2));
					
					% remove the cards that constitute the pair in each hand
					tc1(tc1 == v1) = [];
					tc2(tc2 == v2) = [];
					
					% we are left with three different cards for each hand.
					% just like we did before, we first find a max value for
					% each hand that is different than the one in the other
					ti = 3;
					
					while ti > 0 && tc1(ti) == tc2(ti)
						
						ti = ti - 1;
						
					end
					
					% then we compare the different max values
					if tc1(ti) > tc2(ti)
						
						s = s + 1;
						
					end
					
				else % if the two hands are nothing special (all cards are different)
					
					% again, as we did before, see which max value of each hand
					% is different than the one in the other hand, then compare
					tc1 = sort(findv(c1));
					tc2 = sort(findv(c2));
					
					tc1(tc1 == v1) = [];
					tc2(tc2 == v2) = [];
					
					ti = 4;
					
					while ti > 0 && tc1(ti) == tc2(ti)
						
						ti = ti - 1;
						
					end
					
					if tc1(ti) > tc2(ti)
						
						s = s + 1;
						
					end
					
				end
				
			end
			
		end
		
	end
	
	output = s; % semicolon at the end so you wouldn't cheat! :)
end

Contact us