SortInPlace not working as expected - arrays

I'm trying to make a program that implements a card game. However, sorting a deck (array of cards) gives unexpected output.
My Card.swift file has the following comparison function, which first sorts by :
// For Comparable
public func <(left: Card, right: Card) -> Bool {
if left.suit < right.suit {
return true
}
return left.rank < right.rank
}
Each Card has a Rank and a Suit (defined in Rank.swift and Suit.swift), which are Int enums with the following comparison operator:
public func <(left: Rank, right: Rank) -> Bool {
return left.rawValue < right.rawValue
}
When I make a Euchre deck:
func makeEuchreDeck() {
for suit in 1...4 {
for rank in 9...14 {
deck.append(Card.init(r: rank, s: suit))
}
}
}
and then sort it (via deck.sortInPlace()), it gives the following output (using the raw values for the Rank and Suit):
9 of 1
9 of 2
9 of 3
9 of 4
10 of 1 //inconsistency here
11 of 1 //something about Clubs makes it act up
12 of 1
10 of 2 //it acts normally except for Clubs from here on
10 of 3
10 of 4
11 of 2
11 of 3
11 of 4
12 of 2
12 of 3
12 of 4
13 of 1 //back to normal here
13 of 2 //yes, including Clubs
13 of 3
13 of 4
14 of 1
14 of 2
14 of 3
14 of 4
Questions
Why is is acting so buggy with the 10, Jack, and Queen of Clubs (10, 11, and 12 of 1)?
It looks like the sorting function is acting oppositely of how I intended it. I want it to sort by suit first, then by rank (like how you'd usually sort cards in your hand in a trick-taking game). Expected output is all the Clubs, then all the Diamonds, etc.... Did I get something backwards in my sort function?

You comparison function is not correct, it should be (for example)
public func <(left: Card, right: Card) -> Bool {
// Compare `suit` first. If different, you are done.
if left.suit != right.suit {
return left.suit < right.suit
}
// Same `suit`, need to compare `rank`.
return left.rank < right.rank
}
assuming that you want to sort by suit first and then by rank.
The error in your code is that it does not handle the case left.rank > right.rank correctly. It should return false in that case,
but it actually returns the result of left.rank < right.rank.

Related

Trouble with extra zero in bubble sort in C

I am trying to sort, say, 10 integers in ascending order using bubble sort in C.
This is the code I am using:
#include<stdio.h>
void main()
{
int x[20],i,j;
float temp;
printf("Enter 10 values: \n");
for(i=0;i<10;i++)
{
printf("x[%d]: ",i+1);
scanf("%d",&x[i]);
}
for(i=0;i<10-1;i++)
{
for(j=0;j<=10-i-1;j++)
{
if(x[j]>x[j+1])
{
temp=x[j];
x[j]=x[j+1];
x[j+1]=temp;
}
}
}
printf("The sorted list in ascending order is \n");
for(i=0;i<10;i++)
{
printf("%5d",x[i]);
}
}
The problem is that I am getting an extra zero as output despite giving only non-zero entries as my 10 integers.
This is the input and the corresponding output I am getting. Note that the second output gives a zero and the value 19 has disappeared from the sorted list:
Enter 10 values:
x[1]: 4
x[2]: 2
x[3]: 7
x[4]: 4
x[5]: 8
x[6]: 2
x[7]: 3
x[8]: 9
x[9]: 13
x[10]: 19
The sorted list in ascending order is
2 0 2 3 4 4 7 8 9 13
--------------------------------
Process exited after 44.89 seconds with return value 5
Press any key to continue . . .
I am unable to locate my precise mistake.
for(i=0;i<10-1;i++)
{
for(j=0;j<10-i-1;j++)
{
if(x[j]>x[j+1])
{
temp=x[j];
x[j]=x[j+1];
x[j+1]=temp;
}
}
}
the bug is when i = 0 then inner loop condition is j<=10-0-1=9, then you compare a[j] and a[j+1], but a[j+1] could be a[10], the array starts from 0 to 19, and you only initialized the first 10 integers(0-9), the left 10 integers(10-19) is 0, so there will be an extra 0 in your result.
change j<=10-i-1 to j<10-i-1, and the code will run as you expect.

Deleting an element from an array in C

so Im supposed to make a game an assignment for class.
Essentially, I decided to re-create a heads up Poker game, running different functions such as int deal(a, b, x, y) where a and b are the hero's cards, and x and y are the villan's.
This function in particular, has me a bit stumped. Effectively, I loop through the array deck, and assign random numbers to a, b, x and y. Then, I will translate each assigned value into a real, unique card, and return that to int main().
The part that I am stuck at is "as each card is selected, it is deleted from the array. It seems that there is no easy way in C to simply remove an element from deck array.
int deal (a, b, x, y)
{
int deck[52] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52};
int heroFirst;
int heroSecond;
int villainFirst;
int villainSecond;
srand(0);
}
Any thoughts?
You don't have to delete anything.
Shuffle your deck array (using a Fisher-Yates shuffle or similar algorithm). Deal each card from the "top" of the deck:
int top = 0;
card1 = deck[top++];
card2 = deck[top++];
card3 = deck[top++];
...
etc. The top variable is the index of the next available card in the deck.
The general outline of your code will be something like
#define DECKSIZE 52
#define HANDSIZE 5
int main( void )
{
int deck[DECKSIZE] = { ... }; // initial deck;
size_t top = 0; // points to next available card
shuffle( deck, DECKSIZE );
int hero[HANDSIZE] = {0}; // 0 means no card has been drawn for
int villan[HANDSIZE] = {0}; // that element.
if ( deal( hero, HANDSIZE, deck, DECKSIZE, &top ) &&
deal( villan, HANDSIZE, deck, DECKSIZE, &top ) )
{
/**
* do stuff with hero and villan hands
*/
}
else
{
/**
* Not enough cards available in deck for two hands.
*/
}
};
Your deal function would look something like
int deal( int *hand, size_t handsize, int *deck, size_t decksize, size_t *top )
{
size_t i;
for ( i = 0; i < handsize && *top < decksize; i++ )
hand[i] = deck[(*top)++];
return i == handsize;
}
This function will return 0 if we run out of cards in deck before we've dealt the hand, in which case you'll need to do...something. Good luck!
If you want to deal a partial hand (such as to replace 3 cards), you'd do something like
if ( deal( &hero[2], 3, deck, DECKSIZE, &top) )
...
This call will overwrite hero[2] through hero[4] with three new cards drawn from deck. With each call to deal, top will be advanced to point to the next available card in the deck.
You can write a discard function that returns cards to the deck. It means keeping a separate bottom variable and updating that:
int discard( int card, int *deck, size_t decksize, size_t *top, size_t *bottom )
{
int result = *bottom < *top && *bottom < decksize;
if ( result )
deck[(*bottom)++] = card;
return result;
}
Obviously, bottom should be strictly less than the deck size and strictly less than top on a discard; otherwise, we haven't managed our deck or hands properly. With a little work, you could make your array "circular", such that top and bottom "wrap around" as necessary. If you exhaust the deck, you can reshuffle (minus the cards in hand, which will be the deck entries between bottom and top) and reset top and bottom as necessary.
Play with this on paper for a little while, and it should become obvious.
EDIT
Addressing questions here:
At which point do you assign deck[5] to a card, for instance
That happens in the deal function, in the for loop. The first time we call deal, we tell it to deal to the hero hand:
deal( hero, HANDSIZE, deck, DECKSIZE, &top )
At this point, top is 0. Assuming we're dealing 5 cards at a time, the first call to deal effectively does this:
Loop iteration 0: hero[0] = deck[0]
Loop iteration 1: hero[1] = deck[1]
Loop iteration 2: hero[2] = deck[2]
Loop iteration 3: hero[3] = deck[3]
Loop iteration 4: hero[4] = deck[4]
When the function returns, the top variable has been updated to 5. The next time we call deal, we tell it to deal to the villain hand:
deal( villain, HANDSIZE, deck, DECKSIZE, &top )
Again, assuming we're dealing 5 cards at a time, the loop effectively does this:
Loop iteration 0: villain[0] = deck[5];
Loop iteration 1: villain[1] = deck[6];
Loop iteration 2: villain[2] = deck[7];
Loop iteration 3: villain[3] = deck[8];
Loop iteration 4: villain[4] = deck[9];
After the second call to deal, top has been updated to 10.
Each time you call deal with the top variable, it will start dealing from deck at the position specified by top, and each time through the loop it will add 1 to top. The loop will exit if one of two conditions is true:
i == handsize - we've dealt all the cards necessary for this hand
*top == decksize - we've reached the end of the array, nor more cards may be dealt.
So, suppose you've dealt a number of hands, and there are only 3 cards left in the deck - if you try to deal 5 more cards, the loop will exit before you've dealt all 5 cards, and we'll return a 0 to indicate that no more cards are left in the deck.
at which point is the desk shuffled randomly?
You would call a shuffle function to do that before the first call to deal:
int deck[DECKSIZE] = { ... };
...
shuffle( deck, DECKSIZE );
...
if ( deal( hero, HANDSIZE, deck, DECKSIZE, &top ) &&
deal( villain, HANDSIZE, deck, DECKSIZE, &top ) )
{
...
}
A simplistic (and not terribly good) implementation of the shuffle function would be:
void shuffle( int *deck, size_t decksize )
{
for ( size_t i = 0; i < decksize; i++ )
{
int r = rand() % (decksize - i)
int tmp = deck[i+r];
deck[i+r] = deck[i];
deck[i] = tmp;
}
}
Basically, what this does is swap each deck[i] with a randomly chosen element from deck[i] through deck[decksize-1] (meaning the element may remain in place). Assume we have 5 cards. The first time through the loop, i points to the first card. We pick an offset from i at random and call it r:
i --> 1
2
3
4 <-- r
5
We then swap the contents of deck[i] and deck[i+r], and then advance i:
4
i --> 2
3
1
5
We pick another r at random from the remaining elements:
4
i --> 2
3
1
5 <-- r
and do another swap and advance i:
4
5
i --> 3
1
2
Lather, rinse, repeat - by the end of the loop, the array is more-or-less randomly shuffled.
No, there is no way in C to delete an element from an array. Indeed, as far as I know there is no way to delete an element from an array in C++, C# or Java either.
Now, that being the case, you have a few options. You can use a sentinel value in your code to mark an element as absent. You can resize your array to actually shrink it by one and relocate all elements backwards one place whenever an element is deleted.
In your example, either 0 or -1 should serve fine as sentinel values.
First at all, make the array deck static.
Next, introduce another static variable initially equal to the lenght of array=52.
Now when a card at a random position is dealt, it can be swapped with the last card in the deck, indexed with arraysize-1, and the arraysize being decreased.
Making these two variables static allows the function to maintain a state between calls. Of course better techniques would encapsulate these variables in a struct (allowing eg multiple games / resetting the deck).
In short, the problem you're really trying to solve isn't one of deleting an entry in an array.. Rather, it is a more encompassing issue: How to perform repeated random selection from a fixed domain without repeating selected values. The method described above is one way to do that. An example of the latter technique using a 20-slot array is below (the value 20 was chosen for short output lines (easy to read). It could just as easily be 52, 1000, etc.):
Code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DECK_SIZE 20
typedef struct Deck
{
int cards[DECK_SIZE];
size_t size;
} Deck;
Deck init_deck()
{
// no shuffle is needed. each selection in draw_card will
// pick a random location in the remaining cards.
Deck deck;
for (int i=0; i<DECK_SIZE; ++i)
deck.cards[i] = i+1;
deck.size = DECK_SIZE;
return deck;
}
int draw_card(Deck *deck)
{
// reset when we run out of cards.
if (deck->size == 0)
{
printf("- reset \n");
deck->size = DECK_SIZE;
}
// generate random location in remaining cards.
// note: susceptible to modulo bias
size_t idx = rand() % deck->size;
// decrement size to consume card and index where
// the card will be swap-stored.
--deck->size;
// swap with last card in remaining cards
int tmp = deck->cards[deck->size];
deck->cards[deck->size] = deck->cards[idx];
deck->cards[idx] = tmp;
// return the drawn card
return deck->cards[deck->size];
}
int main()
{
Deck deck = init_deck();
srand((unsigned)time(NULL));
// draw 300 times. this should reset 15 times, and
// each time a new set of 1..20 should result
for (int i=0; i<300; ++i)
printf("%d ", draw_card(&deck));
fputc('\n', stdout);
}
Output (obviously varies)
7 16 3 20 9 13 6 4 1 12 18 10 14 2 8 17 11 5 15 19 - reset
6 20 14 16 11 2 10 13 4 12 18 5 3 7 19 9 17 8 15 1 - reset
14 1 8 15 13 2 19 16 11 17 5 18 9 12 7 6 3 20 4 10 - reset
18 17 12 2 15 19 1 4 14 10 20 16 9 5 11 13 6 8 3 7 - reset
4 18 5 1 19 16 8 10 9 14 13 17 12 20 7 2 15 6 11 3 - reset
14 16 18 1 5 10 17 3 19 9 8 2 7 13 12 20 4 15 11 6 - reset
16 15 12 13 6 1 17 10 9 7 11 20 8 19 2 18 3 4 14 5 - reset
7 1 8 16 17 5 2 12 13 6 18 20 9 11 14 19 15 3 4 10 - reset
20 13 4 18 7 17 12 15 5 14 2 16 11 3 9 10 1 19 8 6 - reset
5 19 4 17 18 13 8 2 12 7 9 1 11 10 3 14 6 15 16 20 - reset
3 5 10 7 1 15 19 13 16 12 9 8 6 20 4 11 17 18 14 2 - reset
11 14 4 7 15 9 16 18 8 13 12 5 10 19 2 6 20 1 3 17 - reset
10 18 2 4 12 20 14 11 16 13 3 9 8 6 5 7 17 1 15 19 - reset
19 12 20 11 13 9 5 1 10 15 7 2 17 6 3 4 8 14 16 18 - reset
10 3 19 4 6 14 18 11 1 7 9 16 8 13 17 20 2 5 15 12
Notive that on each line, there are twenty selections, and each number in 1..20 appears exactly once per line. How this technique serves you is up to you. A worthy challenge will be how to enumerate the hands held by existing players when a reset (often called a deck-flip) happens. That's an interesting problem to solve, and not one that is as intuitive as it may seem.
Hope it helps.
There are a couple of solutions you could use to solve your problem:
First, is using the vector class, especially the insert and remove functions. here's a good explanation on how it works:
C++ Vectors
Second, which is also my favorite is to use numbers or booleans as indicators. for example, declare a simple boolean array of the same length as your deck. the initial value of all elements would be true. for each card, you'd like to remove from the deck simply change its value to false to indicate it's gone.

C program to check lottery numbers: why some tests fail?

This program takes as an input the following lines:
23 12 33 19 10 8
5
23 19 8 12 60 18
14 60 12 44 54 10
8 3 12 19 33 10
33 15 7 60 12 10
22 12 19 23 33 11
23 12 33 19 10 8 ( The first line ) are the lottery results.
n ( in this specific case, 5 ) informs how many lines will follow below.
Each line has 6 numbers. The number order doesn't matter.
The rules are: numbers range from 1 to 60 ( including 1 and 60 ) and they never repeat themselves in the same line.
The variable "quadra" stores how many lines have got 4 numbers right.
The variable "quina" stores how many lines have got 5 numbers right.
The variable "sena" stores how many lines have got 6 numbers right.
So, a computer program is running some tests over my code below and it's claiming that it goes wrong for most of them, but I can't see what's the problem here. Does anybody have a clue? Is this code wrong, or is there something wrong with the software that's testing this code?
#include <stdio.h>
int main(){
int mega[6];
int v[50500][6];
int n,swap;
int i,j,k; //counters
int quadra,quina,sena;
quadra = 0;
quina = 0;
sena = 0;
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
scanf("%i",&n);
for(i=0;i<n;++i){
for(j=0;j<6;++j){
scanf("%i",&v[i][j]);
}
}
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=0;k<6;++k){
if(v[i][j] == mega[k]){
v[i][j] = 61;
}
}
}
}
//reverse bubble sort
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=j+1;k<6;++k){
if(v[i][j] < v[i][k]){
swap = v[i][k];
v[i][k] = v[i][j];
v[i][j] = swap;
}
}
}
}
for(i=0;i<n;++i){
for(j=0;v[i][j] == 61 && j<6;++j);
if(j == 4) ++quadra;
else if(j == 5) ++quina;
else if(j == 6) ++sena;
}
return 0;
}
Your code is true, I understood and tried the flow of it. Looks fine but if you dont need to sort everyline (and use j as a counter in this loop for(j=0;v[i][j] == 61 && j<6;++j); ), you can use simpler ifstatements to compare real lottery results with the ones that entered. What I mean is that your algorithm is a little complex. Try a simple one and see how it works.
Yes, there are a couple of noteworthy issues with your code:
Compile time indicates possibility of uninitialized variable:
But, run-time results in fatal run-time at unknown source location. Stack overflow. It is likely due to this line:
int v[50500][6];
Increase your stack size. It needs to be about 2.5Mbytes for v alone.
Also, this line may not be what you intended:
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
^
If you meant to loop around the remainder of the code, remove the ; after the for() statement, and use curly braces:
for(i=0;i<6;++i) scanf("%i",&mega[i]) //first line, lottery results
{
scanf("%i",&n);
....

Incorrect output with counting and tallying bits in C

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 tried to use a bit counter to see what is in each room. I am not getting the correct sample output after I redirect the sample output. When I printf("%d", itemCnt[loc]);, my output is 774778414trolls
When I printf("%d", itemCnt[0]);, my output is 0trolls. I'm just trying to get one output right so I can figure out how to get the rest of the 8 outputs. From the sample output, the first number is supposed to be 6, followed by 6, 1, 4, 4 ... and so on. Below are sample inputs/outputs and what I have so far in code.
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
code
int main()
{
// contains x and y coordinate
int first, second;
char third[100];
char fourth[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);
}
Map[second-1][first-1] = third[1];
fgets(fourth, 100, stdin);
// bit counter
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];
}
// print the map
for(int h=0; h<30; h++){
for(int v=0; v<30; v++){
printf("%c", Map[h][v]);
}
printf("\n");
}
// print values
printf("%d", itemCnt[0]);
}
return 0;
}
test is not initialized. It looks like you intended to assign 'third[1]' to test.
Also, 774778414 = 0x2E2E2E2E in hex, and 0x2E is the numeric value of ASCII '.', your initial value for map locations. (Tip: when you see wild decimals like that, try Google. I entered, "774778414 in hex" without the quotes.)
I would also suggest breaking down the code into two functions: the first reads from stdin to populate Map (like you do), and the second reads from stdin to populate 8 C strings to describe your objects. It's important to note, the first loop should not go until end of input, because your posted input continues with descriptions, not strictly 3 fields like the beginning.

Find the longest sequence of ascending numbers in unsorted array

Suppose the Array[10] = {10,6,11,9,-18,0,91,18,24,32}
The largest sequence will be 10,11,18,24,32 or -18,0,18,24,32
The solution to this is make another Array[10] which will store the number of sequences. Starting from the last element 32 which makes just 1 sequence i.e. the number itself.
24 makes 2
18 makes 3
91 makes 1
0 makes 4
-18 makes 5
9 makes 4
11 makes 4
6 makes 4
10 makes 5
The output should be either 5 starting from -18 or 5 starting from 10.
Can anyone help me with the code please.
more or less it will look like that, now you need to translate this to language what you are using
largestSequience = [];
temporaryArray = [];
for (element in array)
{
if (temporatySize not empty and temporarySize[lastElement]>=element)
{
if (temporaryArray.length > largestSequence.length) largestSequence = temporaryArray;
temporaryArray = [element]
}
temporaryArray.add(element)
}
What you want in C++. The running time is O(NlogN), in which N is the size of Array[]
#include<stdio.h>
#include<map>
using namespace std;
int main(void) {
int Array[10] = {10,6,11,9,-18,0,91,18,24,32};
int p[10],next[10];
int i,j,n=10;
map<int,int> places;
for(i=n;i>=0;i--){
map<int,int>::iterator ii=places.upper_bound(Array[i]);
if(ii==places.end()){ //no item on the right is larger
p[i]=1;
next[i]=-1;
}else{
next[i]=ii->second;
p[i]=p[ii->second]+1;
}
places[Array[i]]=i;
ii=places.find(Array[i]);
while(ii!=places.begin()){
ii--;
if(p[ii->second]<=p[i]){
places.erase(ii);
}else
break;
ii=places.find(Array[i]);
}
}
int longestI=0;
for(i=1;i<n;i++){
if(p[i]>p[longestI])
longestI=i;
}
for(i=longestI;i>=0;i=next[i]){
printf("%d\n",Array[i]);
}
return 0;
}

Resources