Cracking Codechef hard problems – Python

<!–
google_ad_client = “pub-4601002425609095”;
google_ad_host = “pub-1599271086004685”;
/* 468×15, created 3/29/09 */
google_ad_slot = “9096275585”;
google_ad_width = 468;
google_ad_height = 15;
//–>

<script
src=”http://pagead2.googlesyndication.com/pagead/show_ads.js&#8221; type=”text/javascript”>
In this blog post, i will be discussing about the hard problems at Codechef.com and how to handle them effectively using Python. This is going to be a “learn by example” post.

So, let’s begin.

Consider the Orders Problem. The problem is big, and i am not going to post it anywhere here.

Now, at one go, you might find it easy, but as you start off with pen and paper, things go a little complicated. A close look will reveal that this is one of the most common sorting technique. Yes, it is Insertion Sorting, that is being done by Sgt Johnny. Let’s analyze how.

The pseudocode for insertion sort goes as follows:


insertionSort(array A)
begin
for i := 1 to length[A]-1 do
begin
value := A[i];
j := i-1;
while j ≥ 0 and A[j] > value do
begin
A[j + 1] := A[j];
j := j-1;
end;
A[j+1] := value;
end;
end;

What we have to do is the opposite of it. We have the sorted list, we have partially the steps covered by each soldier, now we need to find the unsorted list.

Proceeding with the sample input/output given at Orders Problem, we do the following


Input - 0 [1] 0
position - 1st 2nd 3rd

Now move the 2nd soldier 1 place to the left. This is our first iteration. So, at the end of first iteration, we have the following


Position - 2nd 1st 3rd
Modified Input - 1 0 [0]

Next, we will see if there are any further iterations possible. So, we move onto next position in modified input and find that it is 0. This means that the 3rd soldier will not move from it’s place. Now, since there are no more iterations that can be done, we arrive at the position being

2 1 3

which is the solution to the problem.

See if it works good for second sample too. The input is

0 1 2 0 1

So, placing the list in a nice format it becomes. This is iteration 0 (no iteration at all)


Input - 0 1 2 0 1
Soldier - 1st 2nd 3rd 4th 5th

Scan the input from left. See, if there is any non-zero value. Yes, we get a non zero value (1). So, now move the 2nd soldier 1 position left. This is our iteration 1. Note that the first iteration was performed at 2nd element of the Input array. This is important, so that we can start our 2nd iteration at the third element.


At the end of 1st iteration::
MInput - 1 0 2 0 1
Soldier - 2nd 1st 3rd 4th 5th

The third element in MInput (Modified Input) is 2. So, we move the 3rd soldier to two steps on its left. This is what we get at the end of second iteration


MInput - 2 1 0 0 1
Soldier - 3rd 2nd 1st 4th 5th

Is there any scope for further iteration? yes, there is ! So, at the end of third iteration, we get something like


Minput - 2 1 0 1 0
Soldier - 3rd 2nd 1st 5th 4th

Now there is no scope for iterations, and hence we stop and end up with the original list as


3 2 1 5 4

Creating the code
When it comes to programming languages, i am comfortable with only one language – Python. So, i will be posting the code in Python only. Hard luck Java guys 🙂


def SgtJohnnySort(il):
"""Follows the reverse Sgt Johnny Sort and displays the original
unsorted list.
il = input list ex: 0 1 2 0 1
sl = the sorted list; which gradually becomes the unsorted list
"""
n = len(il)
sl = range(1, n+1)
last_moved = 0
for i in range(last_moved, n):
if il[i] != 0:
el = sl[i]
sl.remove(el)
sl.insert(i - il[i], el)
el = il[i]
il.remove(el)
il.insert(i-1, el)
last_moved = i
return sl

In my opinion, this should work. However, i tried this on Codechef, and i could get some runtime error which i am unable to understand. While i am trying to figure out the runtime error, why don’t you have a look at above code and notify if something is wrong 🙂

Codechef – India's biggest Online Programming Battle

CodeChef is India’s biggest and aggressive online programming battlefield. I came to know about CodeChef, a couple of days back only, and no doubt, i am impressed.
Designed in a very elegant manner, using jQuery to the max and with cool color blends, the site offers a nice look and feel. Definitely better than other sites in similar area.

My first Impression with CodeChef.

As i created my account, and logged into the site. There were a couple of things that attracted my attention. The thing that i really liked was live stats. The site gives you live stats of the coders trying to get into problem solving and their result. This creates an adrenaline rush, and you are tempted to do something.

Most of the top coders on this site are from premier Indian Institutes like IIT, IISc and others. You can see the real names of people instead of their hax0r names. This is somewhat non-traditional. Traditionally, programmers all over the world have been known by their IRC nicks only. So, if you see someone over coding arena with the nick ‘pranny’, you can very well assume that his IRC nick is ‘pranny’.

The site offers a wide range of programming languages, from LISP to Java. However, if you watch closely the maximum number of entries come from C++, then comes Java. As per my observation, i have not seen a single entry in Python (my favorite). So, if you are a python enthusiastic, there is lot scope for you.

The April challenge

The April challenge is about to come. For more details log onto CodeChef and see for yourself.


Practise for TopCoder and Google Code Jam

In my opinion, the best place to practise for TopCoder and Google Code Jam is to start off with CodeChef. The easy level practise problems, should be completed accurately and well within time. The medium difficulty ones are good and the difficult ones do require brain.

If you are needing any help with Codechef, you can contact their help section at http://www.codechef.com/help/

The Castle Guard Problem

Problem Statement
We have a rectangular castle. The first floor is protected by some number of guards. We want to have at least one guard in each row and in each column. You are given a String[] castle. The j-th character of the i-th element of castle is either ‘.’ (free cell) or uppercase ‘X’ (guard). Return the smallest number of additional guards we have to place in the castle to achieve our goal.

Constraints
– castle will contain between 1 and 50 elements, inclusive.
– Each element of castle will contain between 1 and 50 characters, inclusive.
– All elements of castle will contain the same number of characters.
– Each character of each element of castle will be either ‘.’ or uppercase ‘X’.

Examples
0)

{ “….”,
“….”,
“….”,
“….” }

Returns: 4

Here we can place 4 guards on one of the diagonals and that will satisfy us.
1)

{ “XX…”,
“.XX..”,
“…XX” }

Returns: 0

No additional guards needed.
2)

{ “….XXXX”,
“……..”,
“XX.X.XX.”,
“……..”,
“……..” }

Returns: 3

3)

{ “……..X..”,
“…X…….”,
“………..”,
“..X…X….”,
“………..”,
“………..”,
“……..X..”,
“………..”,
“………..”,
“……..X..”,
“…..X…..” }

Returns: 6



This code has not yet been tested,
and hence it cannot be guaranteed that this code is a proper solution to the above problem.
Watch the space after some span of time and this will be done.




#include "iostream.h"
#include "conio.h"

char Map[50][50];
int maxE=0, maxC=0;

int scan(int X, int Y, char* dir){
int i=0;
if(dir == "horiz"){
for(i=0;i< maxC;i++){
if(Map[i][Y]=='X')
return 0;
}
return 1;
}
if(dir == "vert"){
for(i=0;i< maxE;i++){
if(Map[X][i]=='X')
return 0;
}
return 1;
}
}

int findShortage(int seedC, int seedE){
static int less=0;
int horiz, vert;
if(seedE > maxE){
return less;
}
horiz = scan(seedC,seedE,"horiz");
vert = scan(seedC,seedE,"vert");
if(horiz && !vert){
findShortage(seedC+1, seedE);
}
if(vert && !horiz){
findShortage(seedC,seedE+1);
}
if(horiz && vert ){
less++;
findShortage(seedC+1, seedC+1);
}
}

void main(void){
clrscr();
int i,j;
cout<>maxE;
cout<>maxC;
for(i=0;i< maxE;i++)
for(j=0;j< maxC;j++){
cout<<"Map["<< i <<"]["<< j <<"]";
cin>>Map[i][j];
}

cout<< findShortage(0,0);
getch();
}

Game development

This Programming Challenge requires you to read in a text file, process the contents of the file and output the results.
The file consists of 50 lines of text. Each line consists of 3 sections: First is 3 characters made up of spaces and digits that you can ignore, then 80 characters which are either a space or a + then another 2 characters. The first 3 and last 2 characters are just 1 or 2 digits line numbers padded with spaces. The important part is the 80 characters.
The file would look something like this…

File starts here:
1 1
27 ++++++++ ++++ +++++++ ++++++++++++ +++ 27
28 ++++++++ ++++ +++++++ ++++++++++++ + ++++ ++++++ 28

This is a map of a game world where each location is either land or sea.Land points are +, sea are spaces. What you have to do is process the 80 x 50 map, determine how many continents there are and output how many continents there are plus a list of those continents, together with the size of each continent. The definition of a continent is one or more connected locations where each location is a +. Connected means that in a 3 x 3 grid around a +, if any of the 8 surrounding locations contains a + then the two are connected.

the map file can be downloaded from this location.

I present the code for this problem as below.



/* C++ */

/*
author : pranav prakash
country : india
email : pranavprakash@programmer.net
*/

#include

char map[50][85];

int getMap(char*);
int scanContinent(int, int , int);
int findNext();

int getMap(char* mapfile){
fstream fl;
char v;
fl.open(mapfile, ios::in);
if(fl.bad() || fl.eof()){
return -1;
}
for(int i=0; i<50; i++){
for(int j=0; j<85; j++){
fl.read((char*)&v, sizeof(v));
map[i][j] = v;
}
}
return 1;
}

int findNext(){
int Xpos=0, Ypos=0, unit=0, i, j;
static int continent=1;

for(i=0; i<50; i++)
for(j=3; j<83; j++)
if(map[i][j] == '+'){
Xpos = i;
Ypos = j;
cout<<"\n\n--- Continent Number: "<< continent<<" ---";
//cout<<"\nXpos: "<< Xpos<<" Ypos: "<< Ypos<<"\n";
unit = scanContinent(Xpos, Ypos, continent++);
cout<<"\nNo. of units: "<< unit;

}

return 0; // No more continents left in the map;

}

int scanContinent(int seedX, int seedY, int continent){
static int count=0;
if(map[seedX][seedY] == '+'){
count++;
map[seedX][seedY] = continent;

scanContinent(seedX,seedY+1,continent);
scanContinent(seedX,seedY-1,continent);

scanContinent(seedX+1,seedY+1,continent);
scanContinent(seedX+1,seedY,continent);
scanContinent(seedX+1,seedY-1,continent);

scanContinent(seedX-1,seedY+1,continent);
scanContinent(seedX-1,seedY,continent);
scanContinent(seedX-1,seedY-1,continent);
}
return count;
}

void main(void){
if(getMap("map.txt")){
findNext();
}
}

The original problem statement can be viewed at this location.

This solution was actually selected as a correct solution and was in the top 20 codes. The actual content can be seen at this location.

My favourite C questions

1. Write a “Hello World” program in ‘C’ without using a semicolon.


void main()
{
if(printf("Hello World\n"))
{
}
}

2. Write a C++ program without using any loop (if, for, while etc) to print numbers from 1 to 100 and 100 to 1;

I haven’t tried this code, but i think that it will work, please check and tell me…


#include

int one_round = 0;

int loop(int a){
(one_round == 0)?printf("%d\n", a++):printf("%d\n", a--);
(a == 100)? one_round++: one_round;
(a==0)?1:loop(a);
}

int main(void){
loop(1);
return 0;
}

3. C/C++ : Exchange two numbers without using a temporary variable.
The code could be like this …

swap(int a, int b) {
a = a+b;
b = a-b;
a = a-b;
}

4. C/C++ : Find if the given number is a power of 2.


Using the code given in Problem statement 10, or otherwise, convert the number
into binary, if that binary number has only one 1 and that too, on the extreme left,
then the corresponding decimal number is a power of two. However, this process doesn't appeal
much to me. So i am thinking of a better and optimal way.


5. C/C++ : Multiply x by 7 without using multiplication (*) operator.


int mult(int multiplicand, int multiplier) {
int result=1;
for( multiplicand; multiplicand >0; multiplicand -- ) {
result = result + multiplier;
}
return result;
}

6. C/C++ : Write a function in different ways that will return f(7) = 4 and f(4) = 7

This is a simple mathematical problem regarding basic calculus and geometry.

Lets see
f(7) = 4
f(4) = 7
hence, [f(7)-f(4)] / [7-4] = -1
It simply means that the function is a straight line with slope, m = -1.
So let the equation be y=mx+c in slope intercept form.
Now after doing little calculations, we can find that c = 11.
Hence the required function is
 f(x) + x = 11

7. Remove duplicates in array

The code for this goes as follows.

int removeDuplicates(int arr[], int len) {
int Dup;
for( int i=0; i < len; i++){
Dup = arr[i];
for( int j = i; j < len; j++) {
if( Dup == arr[j]) { // Duplicate entry detected
for( int k=j; k < len; k++) {
arr[k] = ar[k+1];
}
}
}
return 0;
}

8. Finding if there is any loop inside linked list.

class Node{
int data;
int traversed;
struct Node *next;

Node(){
data = 9999;
traversed = 0;
}
};

typedef Node* Nodeptr;

Now traverse the Linked List, and keep on marking the data item traversed as 1.
If in the course of traversing, you arrive at a node that has already been traversed,
i.e. its traversed == 1, then there is a loop present in the List.

9. Remove duplicates in an no key access database without using an array

I have absolutely no idea, what is supposed to be done here. Please help me, by posting your answer.

10. Convert (integer) number in binary without loops.

int int2bin(int n) {
static int bin[8], i;
i = -1;
i++;
int a1 = n % 2 ;
bin[i] = a1;
int a2 = n / 2;
if( a2 == 0)
return 0;
int2bin(a2);
}

11. Write a program whose printed output is an exact copy of the source. Needless to say, merely
echoing the actual source file is not allowed.

Such programmes are called Quines. The various possible ways for coding them are given ::


char *f="char *f=%c%s%c;%c#define Q '%c'%c#define N '%cn'%c#define B '%c%c'%c#include
%cvoid main(){printf(f,Q,f,Q,N,Q,N,B,N,B,B,N,N,N);}%c";
#define Q '"'
#define N '\n'
#define B '\\'
#include
void main(){printf(f,Q,f,Q,N,Q,N,B,N,B,B,N,N,N);}

Another method that can be used is as follows::


#include
void main(void) {
fstream fl;
char a;
fl.open("quine.cpp");
while( !fl.eof()){
fl.read((char*)&a, sizeof(a);
cout<< a;
}
fl.close();
}

Save this program as "quine.cpp"

12. From a ‘pool’ of numbers (four ‘1’s, four ‘2’s …. four ‘6’s), each player selects a number and adds it to the total. Once a number is used, it must be removed from the pool. The winner is the person whose number makes the total equal 31 exactly.

???

13. Swap two numbers without using a third variable.

swap(int a, int b) {
a = a+b;
b = a-b;
a = a-b;
}

14. Given an array (group) of numbers write all the possible sub groups of this group.

Well, i think this is a problem regarding to Power Set, i am currently working on it, if you have a better and optimized code, do write it.

If you have any ambiguity or clarifications, please mail me….