Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Patterned and repetitive code problem:
Index -> Programming, Turing -> Turing Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
TokenHerbz




PostPosted: Thu Feb 10, 2011 4:27 pm   Post subject: Patterned and repetitive code problem:

Iv'e been trying to wrap my head around this part of my code and can't seem to minimize its repetitiveness.

I wonder if anyone else could come up with a better minimalism code to do the EXACT SAME as the following code.

Turing:

fcn Check_rows (row_, colm_ : int, symbol_ : string) : int
    Win_Counter := 1
    if GRID (row_ - 1, colm_) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ - 2, colm_) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    if GRID (row_ + 1, colm_) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ + 2, colm_) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    result Win_Counter
end Check_rows

I Have 4 variations of this above code and require all of them.

What this code should accomplish:
It needs to accept R,C variables, and beable to result the sum of the positive checks it does inside itself.
*****NOTE**** That just because the TILE is the correct SYMBOL, DOESNOT MEAN WE GOT A POINT, IN NEEDS TO BE CONNECTED! No spaces aloud.
It needs to check a 2x2 space AROUND the original R,C values.
It only gets a +1 sum if the checks are SPECIFICLY found in a specific ORDER.
As you can see in Check_rows, It goes LEFT one space then if that is a YES, it goes AGAIN left for the last space. if thats a YES another point.
then it stops, and goes RIGHT, and repeats. There is 2 different FORS because its very important that it counts also, 1 space LEFT and 1 space RIGHT and a "CONNECTED ORDER"

This code will have to do a 2x2 specific patterns like i said, so variations of + and - colms, and then both +/- rows and colums.
Doable? OR what?
Sponsor
Sponsor
Sponsor
sponsor
A.J




PostPosted: Thu Feb 10, 2011 6:21 pm   Post subject: Re: Patterned and repetitive code problem:

Turing:

fcn Check_rows (row_, colm_ : int, symbol_ : string, dist : int, prev : int) : int
    if dist > 2 or dist < -2  then
        result 0
    end if 
    if dist ~= 0 and GRID (row_ - dist, colm_) -> read_Tile_value = symbol_ then
         result 2 + Check_rows(row+(dist-prev), colm, dist+(dist-prev))
    elsif dist ~= 0 then
         result 1 + Check_rows(row+(dist-prev), colm, dist+(dist-prev))
    else result Check_rows(row+1, colm, dist+1, 0) + Check_rows(row-1, colm, dist-1, 0)
end Check_rows
%_% Initial call: Check_rows(row, colm, symbol, 0, -1), however the last parameter can really be anything


The above code utilizes recursion to accomplish what your code did (6 lines shorter). I believe you can shorten it even more if you wanted to. Let me know if this is so.
TokenHerbz




PostPosted: Thu Feb 10, 2011 6:44 pm   Post subject: RE:Patterned and repetitive code problem:

perhaps i can show you a large piece of code because I don't think i can make this work in the way i want it to.

Turing:

%%Rows will be horizontal.  We will check and count each consecutive symbol
%% and return the results.  reach WIN_COUNT is a win.  if we run into a something thats not ours
%% the check end.  We will check both left and right areas first, then go one extra for a total of 2 spaces outwards of checked tile
fcn Check_rows (row_, colm_ : int, symbol_ : string) : int
    Win_Counter := 1
    if GRID (row_ - 1, colm_) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ - 2, colm_) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    if GRID (row_ + 1, colm_) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ + 2, colm_) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    result Win_Counter
end Check_rows
%%Checks the coloms vertically, 5 spaces, (consecetive only)
fcn Check_colms (row_, colm_ : int, symbol_ : string) : int
    Win_Counter := 1
    if GRID (row_, colm_ - 1) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_, colm_ - 2) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    if GRID (row_, colm_ + 1) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_, colm_ + 2) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    result Win_Counter
end Check_colms
%%Checks the forward slash! / / /
fcn Check_forslash (row_, colm_ : int, symbol_ : string) : int
    Win_Counter := 1
    if GRID (row_ - 1, colm_ - 1) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ - 2, colm_ - 2) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    if GRID (row_ + 1, colm_ + 1) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ + 2, colm_ + 2) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    result Win_Counter
end Check_forslash
%checks the backslash direction \ \ \
fcn Check_backslash (row_, colm_ : int, symbol_ : string) : int
    Win_Counter := 1
    if GRID (row_ - 1, colm_ + 1) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ - 2, colm_ + 2) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    if GRID (row_ + 1, colm_ - 1) -> read_Tile_value = symbol_ then
        Win_Counter += 1
        if GRID (row_ + 2, colm_ - 2) -> read_Tile_value = symbol_ then
            Win_Counter += 1
        end if
    end if
    result Win_Counter
end Check_backslash

%%this will call and use all the checks for possible wins (HORIZONTAL/VERTICAL/CROSS)
% and result depending on the counts for it.  I broke up the checks to make it easier to read/understand.
%%It also checks to make sure there are playable tiles, otherwise the game will stop as STALE MATE (CATS EYE)
fcn Check_for_game_win : boolean
    for row : 1 .. GRID_ROW_AMOUNT
        for colm : 1 .. GRID_COLM_AMOUNT
            for plays : 1 .. 2
                if GRID (row, colm) -> read_Tile_value = player (plays).symbol then
                    if Check_rows (row, colm, player (plays).symbol) >= WIN_COUNT or Check_colms (row, colm, player (plays).symbol) >= WIN_COUNT or
                            Check_forslash (row, colm, player (plays).symbol) >= WIN_COUNT or Check_backslash (row, colm, player (plays).symbol) >= WIN_COUNT then
                        player (plays).win := true
                        result true
                    end if
                end if
            end for
        end for
    end for
    %%this checks grid to make sure there are still playable tiles left
    %%otherwise we have no choice to end the game!
    for row : 1 .. GRID_ROW_AMOUNT
        for colm : 1 .. GRID_COLM_AMOUNT
            if GRID (row, colm) -> is_Tile_playable = true then
                result false
            end if
        end for
    end for
    result true
end Check_for_game_win


This is used basically in a simple statement.
Turing:

exit when Check_for_game_win = true


As you can see there is a TON of repeating codes in this section. And I also have plans to change or mark tiles colors accordingly to the check, and I think its a flawd programming code because of all the spots i'd have to add this into.

All my other parts are failrly good, but i'm not satasfied with this part of my code at all, and want to beable to fix it.

Please take note at the patters to! THANKS.
TokenHerbz




PostPosted: Fri Feb 11, 2011 9:32 am   Post subject: RE:Patterned and repetitive code problem:

I've still been working on it, and further more, these "depths" need to be changable, so the 1-2 (or upwards of 5) depending on things, Need to be changed.

If i try a for loop 1 .. DEPTH (say 2) for depts like the above, it doesn't seem to do the orders correctly.

I think im close but its not working right, Assistance would be very much appriciated.
DemonWasp




PostPosted: Fri Feb 11, 2011 10:24 am   Post subject: RE:Patterned and repetitive code problem:

It would be easier to help if you gave a clear problem statement, rather than an implementation of one choice of algorithm. Specifically, what game is this, and what is the win condition you're searching for?
TokenHerbz




PostPosted: Fri Feb 11, 2011 11:45 am   Post subject: RE:Patterned and repetitive code problem:

The game is tic tac toe, however the user has the options to increase the grid size, which will also increase the needed connected tiles to win.

3x3 grid is 3 to win, something like 10x10 could have 4-5 to win. thats what i'm trying to solve.
DemonWasp




PostPosted: Fri Feb 11, 2011 12:43 pm   Post subject: RE:Patterned and repetitive code problem:

So your problem boils down to the following: for each of the directions { vertical, horizontal, diagonal, other diagonal }, check whether any consecutive set of (winSize) elements is the same. If so, report the value that is the same (this will be the symbol of the winning player).


The horizontal case is not too difficult. We scan each row, keeping track of the current symbol and how many of that symbol we've seen before. If we see the same symbol, we increase our count and continue; if we see a different symbol, we change the kind of symbol we're looking at to the new one, and reset our count to 1 (for the 1 symbol we just saw).

Try implementing that first. If you get stuck, I can provide an implementation, but I'd rather you do it yourself.


The vertical case is almost exactly the same. All you need to do is switch the order of iteration so that you iterate through the rows in a column rather than columns in a row. Hint: switch the order of your two for loops.


The diagonal case is a little trickier. Mostly, though, all we need to do is make sure we never go outside the bounds (and, if we were about to step outside the bounds, then obviously we haven't found a match yet!). Instead of iterating over "rows in a column" or "columns in a row", however, we will iterate over "entries in a diagonal". Consider the (\) case, where we take the top left to be (1,1) and the bottom right to be (N,N):

code:

  12345 C
1 .....
2 .....
3 .....
4 .....
5 .....
R


The simplest way will be to start at row N, column 1. You iterate by increasing both the row and col values by 1 at the same time. If the new values are beyond the bounds of the array, you move on to the next diagonal (row N-1, col 1). If the new values are within the bounds of the array, accumulate as you did for the other two cases.

Once you hit row = 0, you will need to switch your starting point to moving along the top, rather than the left side. Your start point should be col 2, row 1 (because you have already checked col 1, row 1), and you should end at col N, row 1.


It should be noted that if you know where your player just played, you can check a little more easily: by checking whether the move they just made was a winning move, rather than checking the whole board.
TokenHerbz




PostPosted: Fri Feb 11, 2011 1:22 pm   Post subject: RE:Patterned and repetitive code problem:

thank you for that reply, I will see if i can fix it and post source later if it works or even if it doesn't.
Sponsor
Sponsor
Sponsor
sponsor
TokenHerbz




PostPosted: Sat Feb 12, 2011 1:06 pm   Post subject: RE:Patterned and repetitive code problem:

Alright after much time I've put into this I'm still at a loss of how to go about this the most efficient way...

I have the basic ideals of what I'm trying to do but have a really hard time putting them into code since i keep finding myself repeating codes which isn't what i'm trying to do.

Some things I've tried:

I tried to create a checkNextTile function that returns a boolean if it matches the symbol its looking for. this looks something like this :
Turing:

fcn CheckNextTile (row, colm : int) : boolean
        if GRID (row_, colm_) -> read_Tile_value = symbol_ then
            result true
        end if
        result false
    end CheckNextTile


What I was trying to accomplish with this was when i go threw my checks, lets just start with ROWS for this example, to have it start at my tile that was just selected right, And go from their -1 in rows same colum checking the tiles, and if it matches add that to the counter to use for later. when it stops we switch to go + of the tile, doing the same, If the counter reaches the win count then theirs a win.

the kind of other fcn i was trying to use also was this kind of set up:
Turing:

fcn WinStreak (chosenTileRow, chosenTileColm, next, prev, winCount, winCounter : int, symbol_ : string) : int
end WinStreak


with this i was wanting to re-call itself adding to the wincount and if it matched or surpassed that we would win for the player.

I wanted to beable to set certain incline/declines on the checks based on all 4 of them set by a case, originally, but after thinking about it i dont think it was needed.
code:

var paths : array 1 .. 4 of int %path changes // horizontal / vertical / forward slash / back slash checks
    case paths of
        label 1 :
        label 2 :
        label 3 :
        label 4 :
    end case


Furthermode, I tried to add a boolean value to know when to correctly EXIT the checks since i have to exit the fcns once to start the forward loop (after doing the back loop) on the searches. I was able to create a working check but again, It was very repetitive like the above code and didn't like it, so this was removed, again.... Mind you it was cut down a bit, but I shall keep up efforts, however...

I do ask for a few more tips or ideas on how to do this? If you want i could try to write out some "idea code" and you can tell me how to better it or perhaps you could for me to put into real code or something of the sorts..

Thanks, Token.
TokenHerbz




PostPosted: Sat Feb 12, 2011 5:34 pm   Post subject: RE:Patterned and repetitive code problem:

Incase all this is to complicated let me simplify what i want to as basic as it can be.

I want to solve tictactoe on a ? x ? grid. it needs ? string in ? row to win.
so 3x3grid "X" string for 3 in a row = win
10x10grid "O"string for 5 in a row = win.
It needs to do this, I Have it set to do this already in the above code, but i would like the code to be better
RandomLetters




PostPosted: Sat Feb 12, 2011 7:19 pm   Post subject: Re: Patterned and repetitive code problem:

You could create an adjacency matrix for the grid, so that two adjacent tiles with the same symbol are connected. Then use the shortest path algorithm to find the path between the ends of an arbitrary line, and if it equal to the length of the line then you win.

Then again, this is a terrible idea, and makes it way harder than just copypasting code! lol.

code:

X-X O
 \|\
O X-X
| |/
O X O


And then this will let you do for example

for r = 0 .. rows
if shortest(r,0,r,columns) <= columns then
result true

basically factoring out the stuff in the middle, by making it more complicated outside Laughing
Tony




PostPosted: Sat Feb 12, 2011 7:41 pm   Post subject: RE:Patterned and repetitive code problem:

Alright, lets say that you have CheckNextTile function. We could check that it returns true N times, or sum the results and see if they add up to N. So for example, to check horizontally going to the right, we'd have something like
code:

sum = 0
for i: 0..N-1
   sum += CheckNextTile(row + i, column, symbol)
end for
return sum == N

Seems pretty simple. There's a bunch of repetition for having to check all 8 directions, but we could use angles and a unit circle to spin around the +/- 1s on rows and columns.

Ruby:

X = :x
O = :o
@grid = [[X, nil, O],
             [X, X, O],
             [O, O, X]]
@win_length = 3 # need 3 to win

# make this work with outside of bounds
def check_tile(r,c,symbol)
   return 0 if r < 0 or r > 2 or c < 0 or c > 2
   return symbol == @grid[c][r] ? 1 : 0
end

def win?(r,c,symbol)
  result = false # assume non-victory
  8.times do |i| # for each of 8 directions
    sum = 0
    @win_length.times do |j| # for up to N steps
      sum += check_tile(r + j*Math.sin((Math::PI / 4)*i).round, c + j*Math.cos((Math::PI / 4)*i).round, symbol)
    end
    result ||= sum == @win_length # record victory if found
  end
  return result
end

And to check if this works
Quote:

# top left
irb(main):053:0* win?(0,0,O)
=> false
irb(main):054:0> win?(0,0,X)
=> true

# top right
irb(main):055:0> win?(0,2,O)
=> false
irb(main):056:0> win?(0,2,X)
=> false

# middle
irb(main):057:0> win?(1,1,O)
=> false
irb(main):058:0> win?(1,1,X)
=> false

# careful about this one. X technically wins, but all the calculations assume to be started from the end of a row of symbols

# bottom right
irb(main):059:0> win?(2,2,O)
=> false
irb(main):060:0> win?(2,2,X)
=> true
Latest from compsci.ca/blog: Tony's programming blog. DWITE - a programming contest.
DemonWasp




PostPosted: Sat Feb 12, 2011 7:45 pm   Post subject: RE:Patterned and repetitive code problem:

@Tokenz: You're making this problem harder than it needs to be.

@Random: While that would work, it would take a lot more programmer time and CPU time. You don't need an adjacency matrix...you just need to check which things are in a row, which is considerably less and turns out to be easier to search for.

Turing:

% Assumptions: map is a (row, col) array from (1,1) to (numRows, numCols)
% Input N is length to match.
% Return either the winning symbol or "" to indicate no win.

fcn checkForWinner ( N : int ) : string

    % Horizontal Check
    for row : 1 .. numRows

        % "State" variables
        var count := 0  % number of consecutive times we have seen "symbol"
        var symbol : string := ""

        for col : 1 .. numCols
            % Same symbol: increment count, check against N
            if ( map(row,col) = symbol ) then
                count += 1
                if ( count = N ) then
                    result symbol
                end if

            % Different symbol: reset count to 1 (for that symbol), start
            % looking at the new symbol
            else
                count := 1
                symbol = map(row,col)

            end if

        end for
    end for


    % Vertical check: this is almost exactly the same as the code above. You
    % can make this ever so slightly less repetitive if you extract the inside
    % of the two for loops to a procedure, but that's nontrivial.


    % Worry about diagonal checks later, after you've understood the vertical
    % checks.

     % If we haven't found a win yet, there isn't one.
    result ""
end checkForWinner


Edit: Converting my C/Java syntax to Turing
TokenHerbz




PostPosted: Sat Feb 12, 2011 9:25 pm   Post subject: RE:Patterned and repetitive code problem:

public class tictatoes {

public static void main( String[] args ) {
String[][] grid = {
{ "b", "b", "a" },
{ "a", "b", "a" },
{ "a", "a", "a" }

};

String[] players = {"a", "b"};

for(int i=0; i< players.length; i++){
String currentPlayer = players[i];
if(checkForWin( grid, currentPlayer, 3 )){
System.out.print( "Winner" + currentPlayer );
}else{
//continue playing game
}
}

}

public static boolean checkForWin( String[][] grid, String player , int winCount) {
return checkForRows( grid, player, winCount )
|| checkForLeft( grid, player, winCount )
|| checkForLeft( grid, player, winCount );
}

public static boolean checkForRows( String[][] grid, String currentPlayer,
int winCount ) {
int currentWinCount = 0;

for ( int i = 0; i < grid.length; i++ ) {
for ( int j = 0; j < grid[i].length; j++ ) {
String currentSlot = grid[i][j];

if ( currentPlayer == currentSlot ) {
++currentWinCount;
if ( currentWinCount > winCount - 1 ) {
return true;
}
} else {
currentWinCount = 0;
}

}

}
return false;
}

public static boolean checkForRight( String[][] grid, String currentPlayer,
int winCount ) {
int currentWinCount = 0;

for ( int i = 0; i < grid.length; i++ ) {
for ( int j = 0; j < grid[i].length; j++ ) {
int row = j;
int col = i;

String currentSlot;
currentWinCount = 0;
while ( row < grid[i].length && col < grid.length ) {
currentSlot = grid[row][col];

if ( currentPlayer == currentSlot ) {
++currentWinCount;
if ( currentWinCount > winCount - 1 ) {
return true;
}
} else {
currentWinCount = 0;
}
col++;
row++;

}

}

}
return false;
}

public static boolean checkForLeft( String[][] grid, String currentPlayer,
int winCount ) {
int currentWinCount = 0;

for ( int i = 0; i < grid.length; i++ ) {
for ( int j = grid[i].length - 1; j > -1; j-- ) {
int row = j;
int col = i;

String currentSlot;
currentWinCount = 0;
while ( row > -1 && col < grid.length ) {
currentSlot = grid[col][row];

if ( currentPlayer == currentSlot ) {
++currentWinCount;
if ( currentWinCount > winCount - 1 ) {
return true;
}
} else {
currentWinCount = 0;
}
col++;
row--;

}

}

}
return false;
}

}
thats something in java anyways, still not satasfied,

I'll read the other posts tho, i'll rely in the morning cause im well, intoxicated atm... <3 replys tho, thx.
Display posts from previous:   
   Index -> Programming, Turing -> Turing Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 14 Posts ]
Jump to:   


Style:  
Search: