Tuesday, September 10, 2013

How I solved UVa 100 - 3n + 1

Problem link: 3n + 1
Many thanks to Praveen and Prasad for bringing this problem back to me after many years. I had solved this problem long back and it had taken more than 3s initially (with AC of course!). 
Prasad started to solve it again and I jumped in too. This time, I submitted 2 solutions:
1. Pre-compute the cycle length of all numbers [1,999999]. Read the inputs and print the outputs from the pre-computed array. Time = 0.442s.
2. I had suggested to Prasad to try and use the idea of computing the cycle length of a number just once. In the previous solution, we compute the cycle length of a number multiple times. I used a stack to keep track of the numbers and once I see a pre-computed cycle length for any number in the sequence, I just unwind the stack and set the cycle lengths for all numbers on the stack. Time = 0.062s.
Both the solutions use scanf, printf, & (bitwise and), >> (right shift), *=, +=.
Looks like the OJ (online judge) runs on really fast processors these days! The OJ upgrade is on :-)
One more spoiler: here's the source code :-) Am finally onto GitHub and it is befitting to add the source of the very first problem I solved years back and solved again due to Prasad.

Saturday, September 7, 2013

How I solved the UVa 10976 - Fractions Again

Here's the problem link:  UVa 10976 - Fractions Again
Caution: This is a spoiler with complete solution. Do not read further if you haven't tried it yet.

Abbreviated problem definition: Given a fraction 1/z, it can be represented as 1/x + 1/y where x >=y. Find all combinations for a given 0 < z <= 10000.

Sample Inputs:
2
12

Sample Outputs:
2 --# of solutions
1/2 = 1/6 + 1/3
1/2 = 1/4 + 1/4
8 --# of solutions
1/12 = 1/156 + 1/13
1/12 = 1/84 + 1/14
1/12 = 1/60 + 1/15
1/12 = 1/48 + 1/16
1/12 = 1/36 + 1/18
1/12 = 1/30 + 1/20
1/12 = 1/28 + 1/21
1/12 = 1/24 + 1/24

Expression:
1/z = 1/x + 1/y
1/z = (y + x)/ (x * y)
z = (x * y)/(x + y) --(1)

z * (x + y) = (x * y)
z * x + z * y = y * x
z * y = (y - z) * x
x = (z * y) / (y - z) --(2)

Looking at the pattern for the samples, we decrease y and find the x,
if possible.

Start with y = 2 * z = 2 * 2 = 4:
1/2 = 1/4 + 1/4
2 = (4 * 4)/(4 + 4) --using (1)  above.

Try y = 3;
2 = (x * 3)/ (x + 3)
2 * (x + 3) = x * 3
2*x + 6 = 3*x
3*x - 2*x = 6
x = 6
So, one more solution found:
1/2 = 1/6 + 1/3

We cannot go further as y becomes equal to 2.
Full answers:
1/2 = 1/4 + 1/4
1/2 = 1/6 + 1/3

Let us look at the second sample:
Start with y = 12 * z = 12 * 2 = 14:
1/12 = 1/24 + 1/24 --Obvious :-)

Reduce y to 23:
Using (1) above we get:
12 = (x * 23)/(x + 23)
12 * (x + 23) = 23 * x
12*x + 276 = 23*x
276 = 11*x
x = 276/11 = 25.0909 => NOT a solution as we need 11 to exactly divide 276

Reduce y to 22:
Using (1) above we get:
12 = (x * 22)/(x + 22)
12*x + 12 * 22 = 22 * x
12 * 22 = 10 * x => NOT a solution

Reduce y to 21:
Using (1) above we get:
12 = (x * 21)/(x + 21)
12 * (x + 21) = 21 * x
12*x + 12 * 21 = 21*x
12 * 21 = 9*x 
x = 28 => We have a solution :-)
1/12 = 1/28 + 1/21

Reduce y to 20:
Using (1) above we get:
12 = (x * 20)/(x + 20)
12*x + 12*20 = 20*x
12*20 = 8*x
x = 30 => we have a solution :-)
1/12 = 1/30 + 1/20

Reduce y to 19:
Using (1) above we get:
12 = (x * 19)/(x + 19)
12*x + 12*19 = 19*x
12*19 = 7*x
x = 32.57 => NOT a solution

Reduce y to 18:
Using (1) above we get:
12 = (x * 18)/(x + 18)
12*x + 12*18 = 18*x
12*18 = 6*x
x = 36 => we have a solution :-)
1/12 = 1/36 + 1/18

Reduce y to 17:
Using (1) above we get:
12 = (x * 17)/(x + 17)
12*x + 12*17 = 17*x
12*17 = 5*x
x = 40.8 => NOT a solution

Reduce y to 16:
Using (1) above we get:
12 = (x * 16)/(x + 16)
12*x + 12*16 = 16*x
12*16 = 4*x
x = 48 => we have a solution :-)
1/12 = 1/48 + 1/16

Reduce y to 15:
Using (1) above we get:
12 = (x * 15)/(x + 15)
12*x + 12*15 = 15*x
12*15 = 3*x
x = 60 => we have a solution :-)
1/12 = 1/60 + 1/15

Reduce y to 14:
Using (1) above we get:
12 = (x * 14)/(x + 14)
12*x + 12*14 = 14*x
12*14 = 2*x
x = 84 => we have a solution :-)
1/12 = 1/84 + 1/14

Reduce y to 13:
Using (1) above we get:
12 = (x * 13)/(x + 13)
12*x + 12*13 = 13*x
12*13 = 1*x
x = 156 => we have a solution :-)
1/12 = 1/156 + 1/13

END when y = 12
There you go :-) 
There could be some optimization that can be performed for quickly
discarding some values of y. Will update.

We have used complete search to arrive at the solution.
One more spoiler: here's the source code

Thursday, September 5, 2013

UVa 10815 - Andy's first dictionary

Andy's first dictionary is an interesting problem which looks quite simple. I got it right at the 5th attempt because, I missed reading the key sentence of the problem: In this problem, a word is defined as a consecutive sequence of alphabets, in upper and/or lower case.
After seeing the key sentence, AC wasn't far off!
Just wanted to say so much :-) 
One more spoiler: here's the source code.

Wednesday, August 7, 2013

How I solved the UVa 12004 - Bubble sort

Here's the Problem link. This blog entry is about how I solved the problem as it brought me lots of joy!

CAUTION: Read further only if you are stuck because the solution lies below. Beware of the spoiler below :-)

Inputs:
Max text cases 1000
each n will be 1<= n <= 100000

Output:
Average value of 'count' which is the number of swaps

Solution:
Number of permutations for 1 2 3 ... n = n!
To get to the average, we need to know the number of swaps and the frequencies of all the swaps so that
the we can multiply the number of swaps and the frequencies and divide by the factorial of the number.

So, a helper C++ implementation was created to print the number of swaps and the frequency of each swap using this format: Num swaps count~~frequency
1: # permutations= 1,       Num swaps count~~frequency for 1:,0~~1,
2: # permutations= 2,       Num swaps count~~frequency for 2:,0~~1,1~~1,
3: # permutations= 6,       Num swaps count~~frequency for 3:,0~~1,1~~2,2~~2,3~~1,
4: # permutations= 24,     Num swaps count~~frequency for 4:,0~~1,1~~3,2~~5,3~~6,4~~5,5~~3,6~~1,
5: # permutations= 120,   Num swaps count~~frequency for 5:,0~~1,1~~4,2~~9,3~~15,4~~20,5~~22,6~~20,7~~15,8~~9,9~~4,10~~1,
6: # permutations= 720,   Num swaps count~~frequency for 6:,0~~1,1~~5,2~~14,3~~29,4~~49,5~~71,6~~90,7~~101,8~~101,9~~90,10~~71,11~~49,12~~29,13~~14,14~~5,15~~1,
7: # permutations= 5040,    Num swaps count~~frequency for 7:,0~~1,1~~6,2~~20,3~~49,4~~98,5~~169,6~~259,7~~359,8~~455,9~~531,10~~573,11~~573,12~~531,13~~455,14~~359,15~~259,16~~169,17~~98,18~~49,19~~20,20~~6,21~~1,
8: # permutations= 40320,   Num swaps count~~frequency for 8:,0~~1,1~~7,2~~27,3~~76,4~~174,5~~343,6~~602,7~~961,8~~1415,9~~1940,10~~2493,11~~3017,12~~3450,13~~3736,14~~3836,15~~3736,16~~3450,17~~3017,18~~2493,19~~1940,20~~1415,21~~961,22~~602,23~~343,24~~174,25~~76,26~~27,27~~7,28~~1,
9: # permutations= 362880,  Num swaps count~~frequency for 9:,0~~1,1~~8,2~~35,3~~111,4~~285,5~~628,6~~1230,7~~2191,8~~3606,9~~5545,10~~8031,11~~11021,12~~14395,13~~17957,14~~21450,15~~24584,16~~27073,17~~28675,18~~29228,19~~28675,20~~27073,21~~24584,22~~21450,23~~17957,24~~14395,25~~11021,26~~8031,27~~5545,28~~3606,29~~2191,30~~1230,31~~628,32~~285,33~~111,34~~35,35~~8,36~~1,
10:# permutations= 3628800, Num swaps count~~frequency for 10:,0~~1,1~~9,2~~44,3~~155,4~~440,5~~1068,6~~2298,7~~4489,8~~8095,9~~13640,10~~21670,11~~32683,12~~47043,13~~64889,14~~86054,15~~110010,16~~135853,17~~162337,18~~187959,19~~211089,20~~230131,21~~243694,22~~250749,23~~250749,24~~243694,25~~230131,26~~211089,27~~187959,28~~162337,29~~135853,30~~110010,31~~86054,32~~64889,33~~47043,34~~32683,35~~21670,36~~13640,37~~8095,38~~4489,39~~2298,40~~1068,41~~440,42~~155,43~~44,44~~9,45~~1,

How to interpret the above data:
# permutations= 6,      Num swaps count~~frequency for 4:,0~~1,1~~3,2~~5,3~~6,4~~5,5~~3,6~~1,
0~~1 => 0 swaps occurs 1 times
1~~3 => 1 swaps occurs 3 times
2~~5 => 2 swaps occurs 5 times
3~~6 => 3 swaps occurs 6 times
4~~5 => 4 swaps occurs 5 times
5~~3 => 5 swaps occurs 3 times
6~~1 => 6 swaps occurs 1 times
The above data is generated using the following permutations of 1, 2, 3, 4
1, 2, 3, 4,
1, 2, 4, 3,
1, 3, 2, 4,
1, 3, 4, 2,
1, 4, 2, 3,
1, 4, 3, 2,
2, 1, 3, 4,
2, 1, 4, 3,
2, 3, 1, 4,
2, 3, 4, 1,
2, 4, 1, 3,
2, 4, 3, 1,
3, 1, 2, 4,
3, 1, 4, 2,
3, 2, 1, 4,
3, 2, 4, 1,
3, 4, 1, 2,
3, 4, 2, 1,
4, 1, 2, 3,
4, 1, 3, 2,
4, 2, 1, 3,
4, 2, 3, 1,
4, 3, 1, 2,
4, 3, 2, 1,
The permutations were generated using the next_permutation algorithm in C++ STL.

Doing a bit more math on:
0~~1 => 0 swaps occurs 1 times
1~~3 => 1 swaps occurs 3 times
2~~5 => 2 swaps occurs 5 times
3~~6 => 3 swaps occurs 6 times
4~~5 => 4 swaps occurs 5 times
5~~3 => 5 swaps occurs 3 times
6~~1 => 6 swaps occurs 1 times
-------------------------------
Adding up just the times: 1 + 3 + 5 + 6 + 5 + 3 + 1 = 24. Interestingly, that is the same as 4!
To get Average, first multiply the num swaps and frequency and add them all to get the numerator.
Numerator = (0*1 + 1*3 + 2*5 + 3*6 + 4*5 + 5*3 + 6*1)
Numerator = ( (6+0)*1 + (1+5)*3 + (2+4)*5 + 6*3) )
Numerator = ( (6*1 + 6*3 + 6*5 + 6*3) )
Numerator = ( 6* (1 + 3 + 5) + 6*3) )
Numerator = ( 3* (2*1 + 2*3 + 2*5) + 6*3)
Numerator = ( 3* (2*1 + 2*3 + 2*5 + 6))
Numerator = ( 3* (1 + 3 + 5 + 6 + 5 + 3 + 1))
Numerator = ( 3* (4!))

Denominator = n! = 4!

Avg = Numerator / Denominator
Avg = ( 3* (4!))/4! = 3
Observation: This is the same as (Max number of swaps / 2) = (6/2) = 3

Doing the same for 1 2 3 4 5
# permutations= 120,     Num swaps count~~frequency for 5:,0~~1,1~~4,2~~9,3~~15,4~~20,5~~22,6~~20,7~~15,8~~9,9~~4,10~~1,
Num permutations = 720
Swaps~~Times
0~~1,
1~~4,
2~~9,
3~~15,
4~~20,
5~~22,
6~~20,
7~~15,
8~~9,
9~~4,
10~~1,
Adding up the Times:
1 + 4 + 9 + 15 + 20 + 22 + 20 + 15 + 9 + 4 + 1 = 120 = 5!
To get Average, first multiply the num swaps and frequency and add them all to get the numerator.
Numerator = ( (0+10)*1 + (1+9)*4 + (2+8)*9 + (3+7)*15 + (4+6)*20 + (5)*22 )
Numerator = ( 10*(1 + 4 + 9 + 15 + 20) + (5)*22)
Numerator = ( 5* (2*1 + 2*4 + 2*9 + 2*15 + 2*20) + 5*22)
Numerator = ( 5* (2*1 + 2*4 + 2*9 + 2*15 + 2*20 + 22))
Numerator = ( 5* (1 + 4 + 9 + 15 + 20 + 22 + 20 + 15 + 9 + 4 + 1))
Numerator = ( 5* (5!))

Denominator = n! = 5!

Avg = Numerator / Denominator
Average = ( 5* (5!))/5! = 5
Observation: This is the same as (Max number of swaps / 2) = (10/2) = 5

Doing the same for 1 2 3 4 5 6:
# permutations= 720,    Num swaps count~~frequency for 6:,0~~1,1~~5,2~~14,3~~29,4~~49,5~~71,6~~90,7~~101,8~~101,9~~90,10~~71,11~~49,12~~29,13~~14,14~~5,15~~1,
Num permutations = 720
Swaps~~Times
0~~1,
1~~5,
2~~14,
3~~29,
4~~49,
5~~71,
6~~90,
7~~101,
8~~101,
9~~90,
10~~71,
11~~49,
12~~29,
13~~14,
14~~5,
15~~1,
Adding up the Times:
1 + 5 + 14 + 29 + +49 + 71 + 90 + 101 + 101 + 90 + 71 + 49 + +29 + 14 + 5 + 1 = 720 = 6!
To get Average, first multiply the num swaps and frequency and add them all to get the numerator.
Numerator = ((0+15)* 1 + (1+14)*5 + (2+13)*14 + (3+12)*29 + (4+11)*49 + (5+10)*71 + (6+9)*90 + (7+8)*101)
Numerator = ( 15*(1 + 5 + 14 + 29 + 49 + 71 + 90 + 101) )
Numerator = ( 15* ((1 + 5 + 14 + 29 + +49 + 71 + 90 + 101 + 101 + 90 + 71 + 49 + +29 + 14 + 5 + 1))/2 )
Numerator = ( 15* ((6!))/2)

Denominator = n! = 6!

Average = Numerator / Denominator
Average = ( 15* ((6!))/2)/6!
        = 15/2
Observation: This is the same as (Max number of swaps / 2) = (15/2)

Yet another observation:
Max number of swaps = n * (n - 1) / 2

What are these numbers:
1
1 + 1
1 + 2 + 2 + 1
1 + 3 + 5 + 6 + 5 + 3 + 1
1 + 4 + 9 + 15 + 20 + 22 + 20 + 15 + 9 + 4 + 1
1 + 5 + 14 + 29 + +49 + 71 + 90 + 101 + 101 + 90 + 71 + 49 + +29 + 14 + 5 + 1
If you Google this, you will be arriving at http://oeis.org/A008302 which is the Triangle of Mahonian numbers.
I saw some numbers, but until I summed them up, I did not realize they were adding up to n!

There was a bit of a detour too where I found out that the maximum coefficient of the Mahonian numbers is a
part of the http://oeis.org/A000140 which is Kendall-Mann numbers used in inversions!!!

Really great to know about the oeis.org - On-Line Encyclopedia of Integer Sequences!
Many thanks to Praveen for showing me the problem and for reviewing this blog enty. 
One more spoiler: here's the source code.

Tuesday, July 9, 2013

CP3: chapter 2 problems progress

1D Array manipulation
UVa 10038 - Jolly Jumpers
UVa 11340 - Newspaper
C++ STL Algorithm
UVa 10107 - What is the Median?
C++ STL Stack
UVa 514 - Rails
C++ STL Map
UVa 11286 - Conformity
UVa 11572 - Unique Snowflakes
C++ STL priority_queue (Java PriorityQueue)
UVa 10954 - Add All
C++ STL queue and deque (JavaQueue and Deque)
UVa 110344 - Ferry Loading IV

Thursday, June 27, 2013

CP3: Chapter 1 problems progress

Section 1.3.3:
Solved Super easy problems: 
UVa 00272 - TEX quotes
UVa 11172 - Relational operators
UVa 11498 - Nlogonia
UVa 11727 - Cost Cutting
Solved Easy problems:
UVa 11942 - Lumberjack sequencing
UVa 11799 - Horror Dash
UVa 11559 - Event Planning (2)
Solved Medium problems:
UVa 00119 - Greedy gift givers
Section 1.4:
UVa 401 - Palindromes
10945 - Mother bear

Sunday, June 23, 2013

Book: Competitive Programming 3 (CP3)

Got the book "Competitive Programming 3" from lulu.com yesterday. Here's the supporting site for the book. The ebook is not going to be available until next year :( which is not a good thing for me. I like to search for content and the ebook would have been really good. I have the first edition of the ebook (bought it in place of buying the 2nd edition by mistake.) The first edition of the ebook is available for free from the supporting site.

This took about 23 days from the order date to reach India. Check the home page before you place the order because lulu could be offering some discounts. I did not check and probably lost saving 5%.

Lots of learning ahead.

Bought 2 more copies for my friends :-). Because of this book, I have solved 108 UVa problems now (5-Dec-2013)

Monday, April 8, 2013

Thoughts on UVA: 10137: The trip

The trip is a very interesting problem, but the fact for me is that I haven't been able to solve it even after a long time. I have collected all the test cases available in the board and all except 1 test case fails and I have no idea how to solve it. Here's the failing test case:
15
0.01
0.03
0.03
0.03
0.03
0.03
0.03
0.03
0.03
0.03
0.03
0.03
0.03
0.03
0.03
The expected answer is: $0.02, while my solution says $0.01. 
To me, it looks like there is some key piece in the problem statement that is missing for me to correctly figure out the answer. I also felt that arriving at my current solution was also not very straight forward. I believe that clearing up the problem statement will help people to understand it better and solve it. The problem's success rate is average probably because of this reason.
My learnings:
1. Program to use money like the way it is being by people. Do not go for floats and doubles. That will help in avoiding magic like floor, ceiling. I got this hint from Prof.Skiena's programming challenges videos. The original link seems to be dead :(
2. The way to compute average is very key to be able to get to a solution and to be able to explain it to others. What is a solution if it cannot be understood by others? What is a solution if it cannot be explained to others?

Friday, April 5, 2013

UVA: 11942: Lumberjack Sequencing and 11461: Square numbers

Got both problems Accepted.
11942: Lumberjack Sequencing - tried binary search and found it to be tedious to program and difficult to get right. Switched to linear search and it simplified the number of cases to be handled.
11461: Square numbers - interesting thing here is that we need to remember the length of the beards as we proceed. I was thinking of comparing diff(i - 1, i) with diff(i, i + 1), but again, need to remember the history. So, I kept the implementation simple by remembering the last diff and the current.
Small problems can teach us quite a bit.
Thanks to Alluri for solving the problems ahead of me and recommending them to me.

Monday, March 4, 2013

CodeChef March challenge 2013 problems

Solved Approximately (APPROX) and Tourist Translations (TOTR). APPROX could have been solved a bit more mathematically and TOTR could have been more efficient.
A question that an algorist has to ask: Can I do better?