Showing posts with label looping. Show all posts
Showing posts with label looping. Show all posts

Wednesday, February 9, 2011

Intelligent Code

Greetings

Every problem in Computer Science can be solved by accounting for every possible permutation that the program might encounter. Naturally this is not an efficient practice, especially when  the number of possibilities can grow exponentially, reaching billions in no time. To effectively solve such problems, we need to implement  a kind of logic, based on our own thinking while problem solving. This inherent 'common sense' of humans can help create powerful algorithms to solve computer problems, without the aid of brute force. An example of such a problem is a computer game (Source .cpp, and .exe), where a computer tries to guess a users' choice within a given range. If the users' choice is >= the computers' guess, the user inputs 0. If the user's choice is < than the computer;s guess, the user inputs 1. Naturally, the computer can iterate through all numbers in the range from lowest to highest and check whether the computers' guess matches the users' choice and arrive upon the answer when the user inputs one(the users' choice will be the current computers' guess - 1). However what if the range extended from 1 to 2^10? Does it make sense to loop through all those numbers, check for user input and output the answer? This method is not time or user friendly. However, if we implement an algorithm that imitates the way we think when solving such a problem, we can arrive upon an extremely efficient solution for this problem. Consider the range 0 to 16. The user's choice is 11. Now lets add 1 to 0 and 1 to 16, to make the range 1-17. This is done because we will than have 2 nice halves of the range: 1-8 and 9-17. This idea of dividing the range into half will be central to out algorithm. You will get why I do this later. Now the computer has 1\16 or 6.25 % chance of guessing the right user's choice. If it iterated through all the values of the range and checked it against the user input, the probability of the program guessing the right choice will be increased to 6.67% -> 7.14 %...etc.(Not really, but for the time being, let us consider the case to be true). What should the program do to arrive upon the answer faster and in fewer tries? It should try to increase the probability of getting the right answer in each successful turn by a greater rate. For example in the range 1-17, the computer programs' first guess has to be (1+17)/2 = 9 or the average of the range extremes. Why? Because if the user inputs 1, the users' guess is less than 9, so it is in the range 1-8. Alternatively, if the user inputs 0, the users' guess will be greater than or equal to 9, and thus in the range 9-16. What have we achieved here? We have increased them probability of the computer guessing the right answer in the next turn to a whooping (1/8)% = 12.5%, which is the double the probability of guessing the right answer of the programs' first turn. Compare this with the 6.67% probability while iterating through all values!Now since the user's choice is 11, he will input 0, and now the computer program will carry out the same operation, although this time on a different range, that is 9-16. After this turn, the probability of guessing the answer right will increase to 25%, then to 50% and finally to 100% When it reaches 1000%, the program will have the answer! his method only works on ranges whose higher extreme can be expressed as:
Log2(Higher Extreme) = some Natural Number.
Therefore 16 works(log2(16) = 4), so does 8. 32 and 4096. The number of guesses the program will make is log2(higher Extreme). In the case of the higher Extreme being 16, the program will make 4 guesses, in the case of 32, it will make 5 guesses and so on.
I have provided the links to the source code and .exe file of this 'game'. Feel free to edit it, distribute it and use it, although with proper credit!

Link to .cpp source file.
Link to .exe playable game file.


This is not the end

Aravind Rao

Thursday, November 25, 2010

Day of the Knight

Recursion n. See recursion
Search v. Definition hidden at the end

Greetings
I am came across an interesting problem sometime back on the net. The problem in a nutshell was to calculate the least of amount of steps that it would take a knight to get from square(a,b) to square(x,y). The real task at hand was to map out the whole chessboard, with values denoting the depth or breadth level from the starting square. This question could be solved two ways, using either the Depth First Search Method, or the Breadth First Search Method. I am going to speak about them in this post.
DEPTH FIRST SEARCH:

The Depth First Search or DFS is a recursive searching method, where by, on goes down as long as they can until they hit a dead end. When they do, they go one up, and starting going down again, although this time in a different path. Consider it like this. Imagine a house full of rooms. Inside these rooms there are more rooms, inside which there are even more. Your task is to find how many rooms one has to go through to get to room 8. Diagram given below.
The room location map.

In a typical DFS search, the longest search order would be something like this:
Start->1->4(Dead End!)->1->5->9->5->1->Start->2->6->10->6->11->6->2->Start->3->7->12->7->3->8

In a typical DFS search, the shortest search order would be something like this:
Start->3->8
      ...............and many possible permutations in between.

As you can see, something that is just two levels away from the start takes a maximum of 23 node visits, where as the shortest one takes just 3 node visits. There is no way to ensure the DFS method to make the shortest node visits, as the DFS wont know the location of the node in absolute terms, only in relationship to other nodes. In part, the DFS has such a high, unacceptable worst case scenario result is because many of the nodes are re-visited many times over.(Start, 1, 5, etc). The difference between the best and worst cases is way too big for the search to be efficient.

BREADTH FIRST SEARCH

The search technique in BFS involves grouping nodes with the same absolute distance nodal distance from Start Point in the same breadth. Imagine that after the BFS technique identifies the nodes with nodal distance 1 from the start point. All these nodes are in Breadth Level 1. These nodes will then be pushed into a stack, where EACH on of these nodes will become the Start Point. Now the nodes with a nodal distance of 1 from these Start points will be grouped in Breadth Level 1 more than than the breadth level of their starting points, something like (Node Level = Start Point Level + 1). In this manner all the nodes will be mapped and assigned a value denoting their absolute nodal distance from the first Start Point. Here is a diagram.

The room Location Map, now with Breadth levels.

In a typical BFS search the search order would be something like this:
Start->1,2,3 stack.push(1,2,3)-1st Level
loop through stack as long as there are nodes.
1->4,5 stack.pop(1) stack.push(4,5)-2nd Level
2->6 stack.pop(2) stack.push(6)-2nd Level
3->7,8 stack.pop(3) stack.push(7,8)-2nd Level //Stop here, 8 is found
4->Dead End! stack.pop(4)-3rd Level
5->9 stack.pop(5) stack.push(9)-3rd Level
6->10,11 stack.pop(6) stack.push(10,11)-3rd Level
7->12 stack.pop(7) stack.push(12)-3rd Level
8->Dead End! stack.pop(8) -3rd Level
9->Dead End! stack.pop(9) -4th Level
10->Dead End! stack.pop(10) -4th Level
11->Dead End! stack.pop(11) -4th Level
12->Dead End! stack.pop(12) -4th Level

Another, faster case
Start->3,2,1 stack.push(3,2,1)-1st Level
loop through stack.
3->7,8 stack.pop(3) stack.push(7,8)-2nd Level //Stop here, 8 is found

As you can see, each node is not visited more than once, only its location is pushed into the stack. After its immediate nodes are visited, it should be popped out or removed, otherwise you will have an infinite loop.
The difference between the best and worst case scenarios is not much, and is generally more efficient than DFS, as it takes less time, resources and searched intuitively.

The C++ program that I built also uses the same technique of BFS to solve the problem. Have a look at it, annotations are included and post your feedback or questions regarding the program.
Link for the .cpp File
Link for the .exe File

 Until the NXT post

Aravind Rao, chief Hacker(claimed)