Creating a state diagram from high level description - computation-theory

For the language L = {ww | w∈{a,b}*} over Σ={a,b}
For the high level description I wrote,
"1. Place marker in front
Sweeping back and forth, check if length is even, if odd reject.
Place marker at end
Sweeping back and forth, move each marker towards the middle. Compare each letter, erase if equal, reject is not.
If markers meet in the middle, accept."
I just have no idea how to turn this turing machine into a state diagram.

Related

Can we reach all the stones by incremented jumps

There are N stones arranged in a circle. A frog sits on the first stone. The frog keeps jumping in clock-wise direction from stone to stone. It skips the stones in increments of 1 for each jump. ie, for the first jump it will skip 0 stones, it skips one stone for the 2nd jump, 2 stones for the 3rd jump and so on.
The task is, given the number of stones N, find out if the frog will reach all the stones.
Eg:
N=1 ---> true
N=2 ---> true --> jumps=(1,2)
N=3 ---> false --> jumps=(1,2,1,1,2,1,1,2,1.....)
N=4 ---> true --> jumps=(1,2,4,3)
I have tried out for different values for N. All I could see was, if N is a power of 2 then all stones can be reached. Also if the any stone is visited more than once before visiting all the stones, then the answer is false. I could not find a reasoning for the observations and hence could not prove it.
I think you're thinking about this the wrong way. Don't get me wrong, it's cool to do mathematical analysis and come out with a simple result, like, "All stones can be reached if and only if N is a power of 2." (And in fact, I believe that that result is correct.) But you don't need to find that sort of result in order to write an algorithm that can answer the question.
Instead, your algorithm can just simulate the frog's jumps (which you've obviously already figured out how to do), and see if it hits every stone. The only tricky part is that the frog plans to continue jumping forever, and obviously you want your algorithm to finish in a finite amount of time. The key insight is that the frog's sequence of jumps will always end up in a loop, so you only need to continue simulating the sequence long enough to be sure that you've entered the loop and completed one pass through it.
How do we know this?
To see why, imagine that we know that the frog has just jumped from stone #i to stone #j. Is that enough to tell us where the frog will jump to next? The answer is "yes"; we don't know whether the frog thinks it skipped j−i−1 stones vs. N+j−i−1 stones vs. 2N+j−i−1 stones or whatnot, but it doesn't matter, because the next stone it lands on doesn't depend on whether the next jump skips j−i stones vs. N+j−i stones vs. 2N+j−i stones — these are all equivalent. So if we know its last jump then we know its next jump, and if we know its next jump then we know the jump after that, and so on: so this one jump is enough to determine the whole rest of the sequence of stones.
This means that there at most N2 possible "states" that the sequence can be in, always determined by the prior stone and the next stone, where each state fully determines all subsequent states. So if you simulate the sequence through at least N2 states, then either you've visited every state exactly once or you've visited some state at least twice (by the pigeonhole principle), so you've necessarily hit all the states you're going to, which means you've necessarily landed on all the stones that you're going to.
That gives you an algorithm in O(N2) time and O(N) space.
You can potentially improve this by
tracking which states you've already visited, and terminating as soon as you find that you've returned to a state.
tracking how many stones you've already landed on, and terminating as soon as you find that you've landed on all of them.
which would complete in O(N) time if you're right that "if the any stone is visited more than once before visiting all the stones, then the answer is false", while still behaving correctly (and still within O(N2) time) if that theory is wrong.

How to handle multiple letters in a Wordle game

I'm making a Wordle type game (you guess a word, if your guess has the right letter in the right spot the guessed letter should go green, if it is the right letter but the wrong spot it shoulod go yellow). I can't quite figure out the logic for colouring the squares when there are multiple letters in the guess.
Right now I have something like:
For X = 1 to 2
If GuessLetter(X) = WordLetter(X) then set GuessLetter(X) to green
Else if GuessLetter(X) is in WholeWord then set GuessLetter(X) to yellow.
Loop
However in the case of the word being AS and the guess being AA, this logic will set the first A green (right letter, right spot, then the second letter yellow (right letter, wrong spot). The correct result should be Green, no colour as there is only one A in the word.
What is the most efficient logic to stop a duplicate guess letter being coloured incorrectly yellow?
I am thinking something like count unique letters in the word and the guess, and skip letters in the guess that exceed the count of that letter in the word. But this does not feel very elegant. Is there a better way?
I'm doing this in javascript but interested in the general logic most of all.

Pacman AI - Minimax Application - Avoiding repeated game tree states

In the context of a project, following the UC Berkley pacman ai project (its second part), I want to implement the minimax algorithm, without alpha-beta pruning, for an adversarial agent in a layout small enough that recursion is not a problem.
Having defined the problem as a 2-player (we assume only 1 ghost), turn taking, zero-sum game with perfect information, applying the recursive would be pretty trivial. However, since many different strategies can end up in the same game state (defined as a tuple of pacman's position, the ghost's position, the food's position and the player currently playing), I wanted to find a way to avoid recomputing all those states.
I searched and I read some things about transposition tables. I am not really sure on how to use such a method however and what I thought I should implement was the following:
Each time a state, not yet visited, is expanded, add it to a 'visited' set. If the state has already been expanded, then if it's the max player's turn (pacman) return a +inf value (which would normally never be chosen by the min player), if it's min's turn return -inf accordingly.
The problem with this idea, I think, and the reason why it works for some layouts but not others, is that when I hit a node, all the children of which have already been expanded, the only values I have to choose from are +/- infinities. This causes an infinite value to propagate upwards and be selected, while in fact it is possible that this game state leads to a loss. I think, I have understood the problem, but I can't seem to find a way to get around it.
Is there any other method I could use to avoid computing repeated game states? Is there a standard approach to this that I am not aware of?
Here is some pseudocode:
def maxPLayer(currentState, visitedSet):
if not isTerminalState
for nextState, action in currentState.generateMaxSuccessors()
if nextState not in visitedSet
mark nextState as visited
scores = scores + [minPlayer(nextState, visitedSet)]
if scores is not empty
return bestScore = max(scores)
else
return +inf #The problem is HERE!
else
return evalFnc(currentState)
end MaxPlayer
def minPlayer(currenstState, visitedSet):
if not isTerminal
for nextState, action in generateMinSuccessors()
if nextState not in visitedSet
mark nextState as visited
scores = scores + [maxPLayer(nextState, visitedSet)]
if scores is not empty
return bestScore = min(scores)
else
return -inf #The problem is also HERE!
else
return evalFnc(currentState)
end MinPlayer
Note that the first player to play is max and I choose the action that has the highest score. Nothing changes if I take into account infinite values or not, there are still instances of the game where the agent loses, or loops infinitely.
I think the main shortcoming in your approach is that you consider already visited states as undesirable targets for the opponent to move to. Instead of returning an infinity value, you should retrieve the value that was computed at the time when that state was first visited.
Practically this means you should use a map (of state->value) instead of a set (of state).
Only in case the value of the first visit is not yet computed (because the recursive call leads to a visit of an ancestor state), you would need to use a reserved value. But let that value be undefined/null/None, so that it will not be treated as other numerical results, but will be excluded from possible paths, even when backtracking.
As a side note, I would perform the lookup & marking of states at the start of the function -- on the current state -- instead of inside the loop on the neighboring states.
Here is how one of the two functions would then look:
def maxPLayer(currentState, evaluatedMap):
if currentState in evaluatedMap
return evaluatedMap.get(currentState)
evaluatedMap.set(currentState, undefined)
if not isTerminalState
bestScore = undefined
for nextState in currentState.generateMaxSuccessors()
value = minPlayer(nextState, evaluatedMap)
if value != undefined
scores.append(value)
if scores is not empty
bestScore = max(scores)
else
bestScore = evalFnc(currentState)
evaluatedMap.set(currentState, bestScore)
return bestScore
end MaxPlayer
The value undefined will be used during the time that a state is visited, but its value has not yet been determined (because of pending recursive calls). If a state is such that the current player has no valid moves (is "stuck"), then that state will permanently get the value undefined, in other cases, the value undefined will eventually get replaced with a true score.
The problem I was having was finally related with the definition of a 'game state' and how 'repeated states' had to be handled.
In fact, consider a the game state tree and a particular game state x which is identified by the following:
The position of pacman.
The number and position of food pellets on the grid.
The position and the direction of the ghost (the direction is taken into acount because the ghost is considered to not be able to make a half turn.
Now suppose you start going down a certain branch of the tree and at some point you visit the node x. Assuming it had not already been visited before and it is not a terminal state for the game, this node should added to the set of visited nodes.
Now suppose that once you're done with this particular branch of the tree, you start exploring a different one. After a certain, undetermined number of steps you get once again to a node identified as x. This is where the problem with the code in the question lies.
In fact, while the game state as defined is exactly the same, the path followed to get to this state is not (since we are currently on a new, different branch than the original one). Obviously, considering the state as visited or using the utility calculated by the last branch is false. It produces unexpected results.
The solution to this problem is, simply, to have a separate set of visited nodes for each branch of the tree. This way the situation described above is avoided. From there on, there are two strategies that can be considered:
The first one consists of considering looping through already visited states as a worst case scenario for pacman and an optimal strategy for the ghost (which is obviously not strictly true). Taking this into account, repeated states in the same branch of the tree are treated as a kind of 'terminal' states that return -inf as a utility.
The second approach consists of making use of a transposition table. This is however not trivial to implement: If a node is not already in the dictionary, initialize it at infinity to show that it is currently being computed and should not be recomputed if visited later. When reaching a terminal state, while recursing on all nodes store in the dictionary the difference in the game score between the current node and the corresponding terminal state. If while traversing a branch you visit a node that was already in the dictionary return the current game score (which depends on the path you took to get to this node and can change from one branch to the other) plus the value in the dictionaty (which is the gain (or loss) in score form getting from this node to the terminal state and which is always the same).
In more practical terms, the first approach is really simple to implement, it suffices to copy the set every time you pass it as an argument to the next player (so that values in different branches won't affect each other). This will make the algorithm significantly slower and alpha beta should be applied even for very small, simple mazes (1 food pellet and maybe 7x7 mazes). In any other case python will wither complain about recursion or simply take too long to solve (more than a few minutes). It is however correct.
The second approach is more complicated. I have no formal proof of correctness, although intuitively it seems to work. It is significantly faster and also compatible with alpha beta pruning.
The corresponding pseudo code is easy to derive from the explanation.

What is a good algorithm to trap the cat in the game “circle the cat”?

I did the cat algorithm based on Breadth-First Search - BFS (because I read about it in another topic here). But now I would like to know if there is a good strategy to CATCH the cat.
For those who do not know, the game is this:
Game Circle the Cat
Nice game. I hadn't seen it before today. I played it for a while, and I've tried to document my algorithm if I was going to code it... Disclaimer: these are just my ideas, while I'm away from my computer, no mathematical proofs that it works or anything like that.
I wanted to start by giving values to each square (I know they're not square-shaped, I'm using 'square' to mean each position in the board). These values will help to indicate which might be the best choice for the cat. For each of the following steps, ignore squares that have been filled in.
Firstly, allocate a DistanceToWin value for each square showing how far to the edge of the board, as follows...
Give each square next to the edge of the board a DistanceToWin value of 1.
Each square adjacent to a 1 gets a value of 2; next to a 2 gets a 3; etc. Keep going until no new values are set. Notice that some squares may not have values set: these have no route to the edge, so if the cat is on one of these squares, it is trapped, and sooner or later, you are going to win.
Now we need to give an indication of HowManyRoutes are possible for each square, as follows... (this could be done at the same time as the assigning of DistanceToWin)
Each square with DistanceToWin=1 gets a HowManyRoutes value of 2. (My thinking here is that this represents that the escape cannot be blocked: one more step, and you can't block two routes in one turn.)
Every other square with a DistanceToWin value has HowManyRoutes set to the sum of HowManyRoutes of the neighbours with a smaller DistanceToWin value.
The square which is the best choice for the cat is the square neighbouring the cat's square which has the highest value of HowManyRoutes divided by DistanceToWin (which I will call Score). If the Score is >= 2, then the cat can/should escape. Each time a square is filled, these values need recalculating across the whole board, unless you feel like working out which squares are impacted.
The algorithm to trap the cat seems to fall into 3 categories:
The cat is encircled (DistanceToWin is not set for the cat's square), and just needs to be finally trapped.
The cat's best escape route needs to be blocked this move (the best Score of a cat's neighbour=1, and the worst Score of any next step on that route is >1)
The cat has loads of escape routes, and you need to limit its options.
For category 1, I'd suggest filling any square next to the cat.
Category 2, fill the square which needs filling.
Category 3: fill in a square which reduces the total Score for the whole board by the largest amount.

Finding all possible segment tilings in a fixed capacity

I am looking for an efficient (more efficient than my combinatorial search) algorithm to tile segments of strings.
I am given two things:
Length of the "area" to cover;
Set of segments (a segment is defined by starting and ending index, as well as a label)
Example:
The total length of area is 5. The given segments are:
- [(0,2), "A B"]
- [(1,3), "B C"]
- [(1,4), "B C D"]
- [(3,5), "D E"]
I am using Python notation to denote segment e.g. (0,2) and its label "A B" a string.
There are 3 ways how one could populate the "area" of size 5 with the given segments with no overlap:
1. ("A B"), ("D E")
2. ("B C"), ("D E")
3. ("B C D")
Other tilings are not possible as an additional segment will overlap with one of the existing tiles already sitting in the "area".
My current approach is to start with one segment and see how many combinations of non-overlapping segments I get. Then two segments and so on till 4. Each combination validity is checked if any of remaining segments cannot be added. If any of remaining segments can be inserted, the whole combination is rejected as invalid.
This works pretty well when there are not many segments and there is little overlap/combinations.
Is there a simple yet efficient algorithm to find these "tilings"?
There is a dynamic programming approach in which you work from left to right along the area to be covered, and at each point work out the number of tilings which finish neatly at that point. To calculate this, look at the segments which cover that point and end at that point. For each of these segments the number of tilings which end with that segment is the number of tilings which end just before that segment starts, and you have already calculated this. So add up these numbers to get the number of tilings which cover that point and end at that point. The answer you want is the number of tilings which cover the end point in the area to be covered and end at that point (assuming want to end neatly or will be forced to).
If you just want one of the possible tilings, you don't need to count the number of tilings terminating at each point, you just want a flag to tell whether there are any tilings terminating at that point or not. It makes it easier to retrieve a possible tiling later if you also note down, at each point where there is a tiling terminating, the tile that terminates at that point for one of the tilings.
Now you can work out a possible tiling that tiles the whole line. Look at the entry for the last character in the string. This gives you the segment that ends that tiling. Given that segment, you know the its length. If it is of length three, and the last offset was offset ten, there must be a valid tiling that terminates at offset seven. You will have noted the segment that terminates at offset seven, which gives you the second last segment in the tiling you need. By looking at the length of that segment, you can work out where to look for a note of the segment just before that, and so on, until you have recovered the entire tiling, from right to left.

Resources