Print tic tac toe board fortran90 - arrays

I am just trying to create a subroutine to print out the current state of the board in tic tac toe. Zeros are blank spaces, 1's are X's, and 2's are O's. I'm not sure what's wrong with my code, but ti would print out the current state, instead it prints out a bunch of different, incorrect boards. Any help at all would be greatly appreciated.
!!!!!!!!!This is my code and subroutine:
program ttt
implicit none
integer, dimension(9) :: board
integer :: playerx
character (len=1), dimension(9) :: cboard
integer :: i, j
!Print board with numbered spots
!print *, "Enter a number 1-9 to play tic-tac-toe"
print *, " "
print "(a11)", " 1 | 2 | 3 "
print "(a11)", "---+---+---"
print "(a11)", " 4 | 5 | 6 "
print "(a11)", "---+---+---"
print "(a11)", " 7 | 8 | 9 "
print *, " "
board = (/ 2, 0, 0, &
0, 1, 0, &
0, 0, 1 /)
playerx = 1
call printboard(board, playerx)
end program ttt
! Subroutine to print out the current state of the board
subroutine printboard(board, playerx)
implicit none
integer, intent(in), dimension(9) :: board
integer, intent(in) :: playerx
character (len=1), dimension(9) :: cboard
integer :: i, j
! board array is series of 1s, 2s, and 0s. set 1 = x, 2 = o, and 0 = " "
if (playerx == 1) then
do i = 1,9
do j = 1, 9
if (board(i) == 0) cboard(j) = " "
if (board(i) == 1) cboard(j) = "x"
if (board(i) == 2) cboard(j) = "o"
if (j < 0 .and. j < 4) then
print "(a1, a1, a3, a1, a3, a1)", " ", cboard(j), " | ", cboard(j), " | ", cboard (j)
print "(a11)", "---+---+---"
endif
if (j > 3 .and. j < 7) then
print "(a1, a1, a3, a1, a3, a1)", " ", cboard(j), " | ", cboard(j), " | ", cboard (j)
print "(a11)", "---+---+---"
endif
if (j > 6 .and. j < 10) then
print "(a1, a1, a3, a1, a3, a1)", " ", cboard(j), " | ", cboard(j), " | ", cboard (j)
print "(a11)", " "
endif
endif
end subroutine printboard
This is what the code produces:
1 | 2 | 3
---+---+---
4 | 5 | 6
---+---+---
7 | 8 | 9
o | o | o
---+---+---
o | o | o
---+---+---
o | o | o
---+---+---
o | o | o
o | o | o
o | o | o
| |
---+---+---
| |
---+---+---
| |
---+---+---
| |
| |
| |
| |
---+---+---
| |
---+---+---
| |
---+---+---
| |
| |
| |
| |
---+---+---
| |
---+---+---
| |
---+---+---
| |
| |
| |
x | x | x
---+---+---
x | x | x
---+---+---
x | x | x
---+---+---
x | x | x
x | x | x
x | x | x
| |
---+---+---
| |
---+---+---
| |
---+---+---
| |
| |
| |
| |
---+---+---
| |
---+---+---
| |
---+---+---
| |
| |
| |
| |
---+---+---
| |
---+---+---
| |
---+---+---
| |
| |
| |
x | x | x
---+---+---
x | x | x
---+---+---
x | x | x
---+---+---
x | x | x
x | x | x
x | x | x

Your code seems to be a little bit complicated. I would have it simplified here and there.
First of all, you can use 2D array to store your data. I think it would be way more natural.
Instead of filling character(1), dimension(3,3) :: cboard based on values from integer, dimension(3,3) :: board you can simply introduce function that will provide required character depending on the value stored inside your board.
When it comes to printing, I think that putting multiple print sections, that behave differently (depending on whether there will be a new line or not), is an overkill.
It is also a good idea to put parts of the code (that are responsible for a certain logic of your application) into modules. This way, you can reuse and replace them. E.g. you can easily add new module that will print your board differently.
When it comes to Fortran, it's a good idea to remember column/row order in arrays. Might be confusing for people coming with the experience based on different languages.
module board_printer
implicit none
contains
function integer2char(x)
integer, intent(in) :: x
character(1) :: integer2char
if(x == 0) then integer2char = ' '
else if(x == 1) then integer2char = 'x'
else integer2char = 'o'
end if
end function integer2char
subroutine printboard(board)
integer, intent(in), dimension(3, 3) :: board
integer :: i
do i = 1, 3
write(*, fmt="(a)") ' '//integer2char(board(i,1))//' | '//integer2char(board(i,2))//' | '//integer2char(board(i,3))//' '
if( i /= 3) then
write(*, fmt="(a)") '---+---+---'
end if
end do
write(*,*) ""
end subroutine printboard
end module board_printer
program ttt
use board_printer
implicit none
integer, dimension(3, 3) :: board
write(*,fmt="(a)") "Enter a number 1-9 to play tic-tac-toe"
write(*,fmt="(a)") " "
write(*,fmt="(a)") ' 1 | 4 | 7 '
write(*,fmt="(a)") '---+---+---'
write(*,fmt="(a)") ' 2 | 5 | 8 '
write(*,fmt="(a)") '---+---+---'
write(*,fmt="(a)") ' 3 | 6 | 9 '
write(*,fmt="(a)") ''
board = reshape((/ 0, 0, 0, 0, 0, 0, 0, 0, 0 /), shape(board) )
call printboard(board)
board = reshape((/ 1, 0, 0, 0, 1, 0, 0, 0, 1 /), shape(board) )
call printboard(board)
board = reshape((/ 0, 0, 1, 0, 1, 0, 1, 0, 0 /), shape(board) )
call printboard(board)
board = reshape((/ 2, 0, 0, 0, 2, 0, 0, 0, 2 /), shape(board) )
call printboard(board)
board = reshape((/ 1, 0, 2, 0, 1, 0, 2, 0, 1 /), shape(board) )
call printboard(board)
end program ttt

Related

How to create a responsive table using C?

I want create a responsive table using C, not C++ or C#, only the old C.
Basically, I create a multiplication table and put lines and borders using the symbols + - and |, but when I use a number with a width greater than one, they are disorganized, so I would like to know some way that, when I put this number, the lines follow it. My code, the actual output and the desired output:
int endTab, selecNum, CurrentRes;
printf("\n\t+----------------------+");
printf("\n\t| multiplication table |");
printf("\n\t+----------------------+\n\n\n");
printf("Enter the table number:");
scanf("%d", &selecNum);
printf("Enter which number will end in:");
scanf("%d", &endTab);
printf("\n\t+-------+---+\n");
// | 1 x 2 | 2 |
for (int i = 1; i <= endTab; i++){
CurrentRes = i*selecNum;
printf("\t| %d x %d | %d |\n", i, selecNum, CurrentRes);
printf("\t+-------+---+\n");
}
return 0;
current output
+----------------------+
| multiplication table |
+----------------------+
Enter the table number:1
Enter which number will end in:10
+-------+---+
| 1 x 1 | 1 |
+-------+---+
| 2 x 1 | 2 |
+-------+---+
| 3 x 1 | 3 |
+-------+---+
| 4 x 1 | 4 |
+-------+---+
| 5 x 1 | 5 |
+-------+---+
| 6 x 1 | 6 |
+-------+---+
| 7 x 1 | 7 |
+-------+---+
| 8 x 1 | 8 |
+-------+---+
| 9 x 1 | 9 |
+-------+---+
| 10 x 1 | 10 |
+-------+---+
expected output
+----------------------+
| multiplication table |
+----------------------+
Enter the table number:1
Enter which number will end in:10
+--------+----+
| 1 x 1 | 1 |
+--------+----+
| 2 x 1 | 2 |
+--------+----+
| 3 x 1 | 3 |
+--------+----+
| 4 x 1 | 4 |
+--------+----+
| 5 x 1 | 5 |
+--------+----+
| 6 x 1 | 6 |
+--------+----+
| 7 x 1 | 7 |
+--------+----+
| 8 x 1 | 8 |
+--------+----+
| 9 x 1 | 9 |
+--------+----+
| 10 x 1 | 10 |
+--------+----+
Things to note:
The output has two columns and you have to maintain width of both the columns for each row.
The maximum width of column 1 is width of selectNum x endTab including leading and trailing space character.
The maximum width of column 2 is the width of result of selectNum x endTab including leading and trailing space.
The length of separator after every row will be based on the maximum width of both the columns.
+---------------+-------+
\ / \ /
+-----------+ +---+
| |
max width max width
of col 1 of col 2
You can do:
#include <stdio.h>
#define SPC_CHR ' '
#define BIND_CHR '+'
#define HORZ_SEP_CH '-'
#define VERT_SEP_CH '|'
#define MULT_OP_SIGN 'x'
void print_label (void) {
printf("\n\t+----------------------+");
printf("\n\t| multiplication table |");
printf("\n\t+----------------------+\n\n\n");
}
void print_char_n_times (char ch, int n){
for (int i = 0; i < n; ++i) {
printf ("%c", ch);
}
}
void print_row_sep (int max_w1, int max_w2) {
printf ("\t%c", BIND_CHR);
print_char_n_times (HORZ_SEP_CH, max_w1);
printf ("%c", BIND_CHR);
print_char_n_times (HORZ_SEP_CH, max_w2);
printf ("%c\n", BIND_CHR);
}
void print_multiplication_row (int m1, int m2, int max_w1, int max_w2) {
printf ("\t%c", VERT_SEP_CH);
int nc = printf ("%c%d%c%c%c%d%c", SPC_CHR, m1, SPC_CHR, MULT_OP_SIGN, SPC_CHR, m2, SPC_CHR);
if (nc < max_w1) {
print_char_n_times (SPC_CHR, max_w1 - nc);
}
printf ("%c", VERT_SEP_CH);
nc = printf ("%c%d%c", SPC_CHR, m1 * m2, SPC_CHR);
if (nc < max_w2) {
print_char_n_times (SPC_CHR, max_w2 - nc);
}
printf ("%c\n", VERT_SEP_CH);
}
void print_multiplication_table (int m1, int m2) {
int col1_max_width = snprintf (NULL, 0, "%c%d%c%c%c%d%c", SPC_CHR, m1, SPC_CHR, MULT_OP_SIGN, SPC_CHR, m2, SPC_CHR);
int col2_max_width = snprintf (NULL, 0, "%c%d%c", SPC_CHR, m1 * m2, SPC_CHR);
for (int i = 0; i < m2; ++i) {
print_row_sep (col1_max_width, col2_max_width);
print_multiplication_row(m1, i + 1, col1_max_width, col2_max_width);
}
print_row_sep (col1_max_width, col2_max_width);
}
int main (void) {
int endTab, selecNum;
print_label();
printf("Enter the table number: ");
scanf("%d", &selecNum);
printf("Enter which number will end in: ");
scanf("%d", &endTab);
print_multiplication_table (selecNum, endTab);
return 0;
}
Output:
% ./a.out
+----------------------+
| multiplication table |
+----------------------+
Enter the table number: 1
Enter which number will end in: 10
+--------+----+
| 1 x 1 | 1 |
+--------+----+
| 1 x 2 | 2 |
+--------+----+
| 1 x 3 | 3 |
+--------+----+
| 1 x 4 | 4 |
+--------+----+
| 1 x 5 | 5 |
+--------+----+
| 1 x 6 | 6 |
+--------+----+
| 1 x 7 | 7 |
+--------+----+
| 1 x 8 | 8 |
+--------+----+
| 1 x 9 | 9 |
+--------+----+
| 1 x 10 | 10 |
+--------+----+
Note that if you want output in the way you have shown, i.e. like this -
+--------+----+
| 1 x 1 | 1 |
+--------+----+
| 2 x 1 | 2 |
+--------+----+
| 3 x 1 | 3 |
+--------+----+
....
....
+--------+----+
| 10 x 1 | 10 |
+--------+----+
then make following change in the statement of for loop of function print_multiplication_table():
print_multiplication_row(i + 1, m1, col1_max_width, col2_max_width);
^^^^^^^^^
arguments swapped
A couple of points:
If you want to maintain the width at the level of numbers printed one down other, in the first column, then calculate the width of maximum digit entered by the user and use it while printing the multiplication row.
Above program is just to show you the way to get the output in desired form. Leaving it up to you to do all sort of optimisations that you can do.
Read about printf() family functions. Read about sprintf(), snprintf() and their return type etc.
This is not the complete solution, but you may be able to work out exactly what you want/need based on the ideas here. (The key ingredient is that log10(), a math library function) will tell how much horizontal space will be needed. Feed it the largest value in each of the 3 numbers columns and you determine the widths needed from that.
#include <stdio.h>
#include <math.h> // for log10()
int demo( int m0, int m1 ) {
char buf[ 100 ]; // adequate
int wid0 = (int)( log10( m0 ) + 1);
int wid1 = (int)( log10( m1 ) + 1);
int widR = (int)( log10( m0 * m1 ) + 1);
int need = 0;
need++; // left 'box'
need++; // space
need += wid0; // first number
need += strlen( " x " ); // mult
need += wid1; // second number
need += strlen( " | " ); // middle box
need += widR; // result
need++; // space
need++; // right 'box'
memset( buf, '\0', sizeof buf ); // start null
memset( buf, '-', need );
puts( buf );
printf( "| %*d x %*d | %*d |\n\n", wid0, m0, wid1, m1, widR, m0 * m1 );
return 0;
}
int main() {
demo( 24, 25 );
demo( 15, 456 );
return 0;
}
Output:
-----------------
| 24 x 25 | 600 |
-------------------
| 15 x 456 | 6840 |
Use the %n directive to gather how many bytes have been printed up to a point and work from there to write your '-' printing loop, for example:
int field_width;
snprintf(NULL, 0, "%d%n\n", 420, &field_width);
char horizontal[field_width + 1];
memset(horizontal, '-', field_width);
horizontal[field_width] = '\0';
Now you can print a horizontal string that's the same width as 420 when printed. Part of your problem is solved by this.
I've adapted my initial example to use snprintf because it occurs to me that you need to work out the column widths from the largest numbers first. In your print loop you'll want to pad out each value to field_width wide; you could use %*d (right justified, space padded) or %-*d (left justified, space padded) or %.*d (zero prefix padded), depending on your choice, for example:
printf("%*d\n", field_width, 1);
... and there's the rest of your problem solved, if I am correct.

How come the following program output is 5, not 4? Could anyone explain?

I came upon a program which outputs 5. I don't know how. Please explain.
int main(void) {
int t[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, *p = t;
p += 2;
p += p[-1];
printf("\n%d",*p);
return 0;
}
I expect the output to be 4.
the pointer moves from t[0] to t[2] here(p+=2;). In the next statement p+= p[-1], I believe pointer moves to t[1] whose value is 2 first and so increased by 2. So I expected output to be 4.
but the actual output is 5. Anyone, please explain?
p = t; // p = &t[0]
p += 2; // p = &t[2]
p += p[-1]; // p += 2; // p = &t[4]
At first, the pointer p points to the beginning of the array t. So it should be something like
p--
|
v
------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
Now by
p += 2
p is increment according to pointer arithmetic. So that p is now pointing to 3.
p----------
|
v
------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
p[-1] is same as *(p-1). ie, the value at the address p-1. This value is 2.
------ p[-1] or *(p-1)
|
|
------|-----------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
After adding 2 to the current value of p, p would now be pointing to 5.
p------------------
|
v
------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
------------------------------------------
So, when you print the value of *p, 5 is output.

Flatten table in Excel using VBA

I'm looking to use VBA to transform a raw data extract into a flattened table for querying. Currently, I have a raw data table in Excel that summarizes the status of Phases A, B, and C for a given Engagement (note: some Engagements may not have data for all 3 phases).
Row| EngagementID | A_date | A_status | B_date | B_status | C_date | C_status
1 | 201 | 2/2 | Approved | | | |
2 | 201 | | | 3/5 | Approved | |
3 | 201 | | | | | 4/1 | Pending
4 | 203 | 2/12 | Submitted| | | |
5 | 203 | | | 2/20 | Approved | |
6 | 207 | 2/5 | Approved | | | |
I need to flatten the table to look like something this:
Row| EngagementID | Date | Status
1 | 201 | 2/2 | Approved
2 | 201 | 3/5 | Approved
3 | 201 | 4/1 | Pending
4 | 203 | 2/12| Submitted
5 | 203 | 2/20| Approved
6 | 207 | 2/5 | Approved
Additionally, I'd like to add a column for the Phase so that I can "tag" each row with the Phase (A, B, or C) that it is associated with.
I've tried the following VBA code, but it flattens the table vertically, as opposed to horizontally (merging 3 rows into 1, as opposed to 3 columns into 1):
Private Sub test()
Dim R As Long
Dim i As Integer
i = 1
R = 2
Count = 0
Do While Not IsEmpty(Range("A" & R))
If Cells(R, 1).Value = Cells(R + 1, 1).Value Then
Count = Count + 1
Else
i = 1
Do While i <= Count
Cells(R - Count, 2 + (2 * i)).Value = Cells(R - Count + i, 2 + (2 * i))
Cells(R - Count, 3 + (2 * i)).Value = Cells(R - Count + i, 3 + (2 * i))
i = i + 1
Loop
i = 1
Do While i <= Count
Rows(R - Count + i).Delete
i = i + 1
R = R - 1
Loop
Count = 0
End If
R = R + 1
Loop
End Sub
Please help!!
Try this code
Sub Test()
Dim a As Variant
Dim b As Variant
Dim i As Long
Dim j As Long
Dim k As Long
a = Range("A1").CurrentRegion.Value
ReDim b(1 To UBound(a, 1) * 3, 1 To 3)
For i = 2 To UBound(a, 1)
For j = 2 To UBound(a, 2) Step 2
If a(i, j) <> "" And a(i, j + 1) <> "" Then
k = k + 1
b(k, 1) = a(i, 1)
b(k, 2) = a(i, j)
b(k, 3) = a(i, j + 1)
End If
Next j
Next i
Range("J1").Resize(k, UBound(b, 2)).Value = b
End Sub

Why this type of power function work?

res = 1;
for ( i = 1; i <= n; i <<= 1 ) // n = exponent
{
if ( n & i )
res *= a; // a = base
a *= a;
}
This should be more effective code for power and I don't know why this works.
First line of for() is fine I know why is there i <<= i. But I don't understand the line where is: if ( n & i ). I know how that works but I don't know why...
Let us say you have a binary representation of an unsigned number. How do you find the decimal representation?
Let us take a simple four bit example:
N = | 0 | 1 | 0 | 1 |
-----------------------------------------
| 2^3 = 8 | 2^2 = 4 | 2^1 = 2 | 2^0 = 1 |
-----------------------------------------
| 0 | 4 | 0 | 1 | N = 4 + 1 = 5
Now what would happen if the base wasn't fixed at 2 for each bit but instead was the square of the previous bit and you multiply the contribution from each bit instead of adding:
N = | 0 | 1 | 0 | 1 |
----------------------------
| a^8 | a^4 | a^2 | a^1 |
----------------------------
| 0 | a^4 | 0 | a^1 | N = a^4 * a^1 = a^(4+1) = a^5
As you can see, the code calculate a^N

How to apply matrices - an understanding request

Suppose I have a cube as
P1(0, 0, 0) P5(0, 0, 1)
P2(1, 0, 0) P6(1, 0, 1)
P3(0, 1, 0) P7(0, 1, 1)
P4(1, 1, 0) P8(1, 1, 1)
Now I need to apply transformation/rotation/scale matrices. Say,
transform = Pt(3, 3, 5)
rotation = 30ยบ
scale = 2x`
Ok. But, where do I put each of these values into the matrices in order to get the final result? That confuses me alot.
edit
Lets say, for the P2, I have:
| 1 | | a b c |
| 0 | x | d e f | = R
| 0 | | g h i |
But what do I have in a,b,c,d,...i ?
To do it with a single operation you need a 4x4 matrix. Look at http://www.engineering.uiowa.edu/~ie_246/Lecture/OpenGLMatrices.ppt for some details and examples.
In the end you chain the transformations like this
point[i] = T1*T2*T3*..*vertex[i]
Each of the 8 points on the corners of the cube are a 3x1 vector. Your matrix transformations are 3x3 matricies.
Rotation about what axis? That will change what that rotation matrix will look like. Here's what it is about the x-axis:
| +cos(theta) -sin(theta) 0 |
Rx = | +sin(theta) +cos(theta) 0 |
| 0 0 1 |
The scale is easy: Multiply all the x-coordinates by a factor of two.
| 2 0 0 |
S = | 0 1 0 |
| 0 0 1 |
Apply these to each of your points.

Resources