Reputation: 117
This is only my 2nd programming class. There are 30 rooms, we have to see what is in each room and tally it. I already used the for loop to go through the 30 rooms and I know I have to use a bit counter to see what is in each room. I don't know how to count the bits in a word. Below are sample inputs/outputs and what I have so far in code.
Sample input:
9 23 @Z
If the key is:
0 gold_bar
1 silver_bar
2 diamond
3 copper_ring
4 jumpy_troll
5 air
6 angry_troll
7 plutonium_troll
And the line is 9 23 @Z then room at 9,23 (character Z with binary: 01011010) has items 1, 3, 4, 6. silver_bar, copper_ring, jumpy_troll, angry_troll
#include <stdio.h>
#include <stdlib.h>
int main()
{
// contains x and y coordinate
int first, second;
char third[100];
char Map[30][30];
// map initialization
for(int x=0; x<30; x++){
for(int y=0; y<30; y++){
Map[x][y] = '.';
}
}
while(scanf("%d %d %s",&first, &second, third) != -1) {
// Condition 1: a zero coordinate
if (first==0 || second==0) exit(0);
// Condition 2: coordinate out of range
if (first<0 || first>30 || second<0 || second>30){
printf("Error: out of range 0-30!\n");
exit(1);
}
// bit counter
for( int bit_p=0; bit_p<8; bit_p++){
}
Map[second-1][first-1] = third[1];
return 0;
}
Sample input:
1 20 @@
2 21 @A
3 22 @#
4 23 @1
5 22 @@
6 22 @@
7 22 @@
8 22 @@
9 23 @Z Here be trolls � not!
10 23 @+
12 23 @@
13 24 @@
11 22 @@
14 22 @2
15 21 @1
16 20 @@
17 19 @@
18 20 @@
19 19 @@
20 18 @@
21 17 @*
22 16 @*
23 15 @%
0 14 @7
0 gold_bar
1 silver_bar
2 diamond
3 copper_ring
4 jumpy_troll
5 air
6 angry_troll
7 plutonium_troll
Sample Output:
6 gold_bar
6 silver_bar
1 diamond
4 copper_ring
4 jumpy_troll
8 air
15 angry_troll
0 plutonium_troll
Upvotes: 0
Views: 211
Reputation: 2528
The individual bits of a word are not directly accessible with C, so we have to do other things to get at them.
Consider your values, which give which bit is set:
0 gold_bar 00000001B or 0x01
1 silver_bar 00000010B or 0x02
2 diamond 00000100B or 0x04
3 copper_ring 00001000B or 0x08
4 jumpy_troll 00010000B or 0x10
5 air 00100000B or 0x20
6 angry_troll 01000000B or 0x40
7 plutonium_troll 10000000B or 0x80
So with observation, lets consider what will happen if we have the following:
unsigned char test = 'z'
unsigned char res = test & 0x02
Now as you stated 'z' has a binary representation of 01111010 and if we do a logical and with 2 we have:
z: 01111010B
0x02: 00000010B
----------
00000010B
So the expression test & 0x02 evaluates to 0x02. So, how can we use this? We can write something like:
if((test & 0x02) == 0x02)
++cntSilverBars;
Extending this we have, assuming we have appropriately defined variables (i.e cntAuBars would be declared as int cntAuBars and hold the number of gold bars discovered:
if((test & 0x01) == 0x01)
++cntAuBars;
if((test & 0x02) == 0x02)
++cntAgBars;
if((test & 0x04) == 0x04)
++cntDiamonds;
if((test & 0x08) == 0x08)
++cntCuRings;
if((test & 0x10) == 0x10)
++cntJumpyTroll;
if((test & 0x20) == 0x20)
++cntSilverBars;
if((test & 0x40) == 0x40)
++cntAir;
if((test & 0x80) == 0x80)
++cntPuTroll;
While the above will work, it can be re-written as:
int itemCnt[8] = {0}; // array to hold count of items, index is item type
unsigned char test; // holds contents of room.
int loc;
for(loc = 0; loc < 8; loc++) // loop over every bit and see if it is set
{
unsigned char bitPos = 1 << loc; // generate a bit-mask
if((test & bitPos) == bitPos)
++itemCnt[loc];
}
For example, the following program:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
unsigned char test = 'z';
int items[8] = {0};
int loc;
int ndx;
for(loc = 0; loc < 8; loc++)
{
unsigned bitPos = 1 << loc;
if((test & bitPos) == bitPos)
++items[loc];
}
for(ndx = 0; ndx < 8; ndx++)
{
printf("%d, ", items[ndx]);
}
return 0;
}
can be compiled as: gcc -g -ansi -pedantic -Wall temp.c -o temp
, and when run produces the following array (when view in a debugger):
(gdb) print /t 'z'
$7 = 1111010
(gdb) print items
$8 = {0, 1, 0, 1, 1, 1, 1, 0}
Upvotes: 4
Reputation: 3200
This code examines a character and fills an array of 8 ints with value 0 if the bit at that position is 0 and value 1 if the bit at that position is 1
char c = 'Z';
int bits[8];
int n;
char aux = c;
for ( n=0; n<8; ++n ) {
if ( aux & '\1' )
bits[n] = 1;
else
bits[n] = 0;
aux = aux >> 1;
}
aux & '\1'
and aux = aux >> 1
are the heard of the code.
'\1' is the character with ASCII code 1 thus its bit at position 0 is 1 and all other bits are 0. When we do a bitwise AND of '\1' with a character we get 1 if that character a 1 at bit position 0 and we get a 0 otherwise.
aux = aux >> 1
will shift bits one position to the left so that in the next operation the bit at postion 0 will be the one which was originally at position 1.
Upvotes: 1
Reputation: 1164
There's no built-in function for accumulating bit counts in a word. For each room, you'll need to check each of the 8 bits and, if that bit is set, increment the appropriate counting variable. There are many ways to do this, but especially for a class you want to do it as clearly as possible.
The basic idea is that you want to compare the word you read in ("third", in your framework) to a single bit mask shifted up to the bit position you're testing. Do the comparison by and'ing the mask against the input in and testing it using if statement. I've dropped a sample into your framework:
// bit counter
for( int bit_p=0; bit_p<8; bit_p++){
if (third & (1 << bit_p))
tally[bit_p]++;
}
The common piece is the structure if (input & MASK) {do_whatever}
. Once you understand why that structure works, you can apply it to many situations.
Upvotes: 0