Skip to content

Commit 57c7c34

Browse files
committed
Reorg files, add apple HID position take home assignment with my implementations, could be wrong, comments needed.
1 parent b3c370f commit 57c7c34

File tree

8 files changed

+391
-0
lines changed

8 files changed

+391
-0
lines changed

.DS_Store

6 KB
Binary file not shown.

Interview/Company/.DS_Store

6 KB
Binary file not shown.
File renamed without changes.
File renamed without changes.

Interview/Company/Apple/.DS_Store

6 KB
Binary file not shown.
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
/*
2+
Question 1
3+
4+
You are given a deck containing N cards. While holding the deck facedown:
5+
6+
1. Deal all the cards facedown onto a table into Y piles like you would if you were playing with a group of people (i.e. card 1 to P1, card 2 to P2, ..., card Y to PY, card Y + 1 to P1, etc).
7+
2. Combine all the piles into a deck by placing P1 onto P2, then P1+P2 onto P3, and so on. This is a round.
8+
3. Pick up the deck from the table and repeat steps 1-2 until the deck is in the original order.
9+
4. For each round, vary the pile count according to a repeating pattern. Start with 3 piles, then 4, then 5, then loop back to 3, then 4 and so on.
10+
11+
Write a program to determine how many rounds it will take to put a deck back into the original order. This will involve creating a data structure to represent the order of the cards. Do not use an array. This program should be written in C only. It should take a number of cards in the deck as a command line argument and write the result to stdout. Please ensure the program compiles and runs correctly (no pseudo-code). This isn't a trick question; it should be fairly straightforward.
12+
13+
Bonus: Output how many rounds should be completed before the deck is adequately shuffled from the original deck for a person who is casually playing a game with cards. Provide your methodology in a comment block.
14+
*/
15+
16+
#include<stdio.h>
17+
#include<stdlib.h>
18+
#include<stdbool.h>
19+
#include<unistd.h>
20+
21+
#define MAX_TOTAL_PILES (5)
22+
#define NUM_PILES (3)
23+
24+
int pileNumberTable[3] = {3, 4, 5};
25+
26+
/* Linked List node */
27+
typedef struct card
28+
{
29+
int val;
30+
struct card* next;
31+
}card_t;
32+
33+
/* Linked list of card_t, or the head of a linked list of cards */
34+
typedef struct pile
35+
{
36+
card_t* top_card;
37+
}pile_t;
38+
39+
typedef struct deck
40+
{
41+
int val;
42+
struct deck* next;
43+
}deck_t;
44+
45+
/* This array only stores the handler of each pile so that they can be
46+
retrieved for cards each pile hold to form a deck */
47+
pile_t pileArr[MAX_TOTAL_PILES];
48+
49+
50+
/**
51+
* @brief helper function to cleat/empty piles
52+
*/
53+
static void resetPiles(void)
54+
{
55+
for(int i = 0; i < MAX_TOTAL_PILES; i++){
56+
pileArr[i].top_card->val = -1;
57+
pileArr[i].top_card->next = NULL;
58+
}
59+
}
60+
61+
/**
62+
* @brief add all the cards in pile to the deck
63+
* @param[in] pile pile that contains cards
64+
* @param[in/out] deck needs to be added with cards
65+
*/
66+
static void addToDeckTail(pile_t* pile, deck_t* deck)
67+
{
68+
/* Find last one in current deck */
69+
deck_t* iter = deck;
70+
while(iter->next){
71+
iter = iter->next;
72+
}
73+
/* iter is pointing to last node at this point */
74+
75+
card_t* iter2 = pile->top_card;
76+
while(iter2){
77+
deck_t* newDeckNode = (deck_t*)malloc(sizeof(deck_t));
78+
newDeckNode->val = iter2->val;
79+
/* add to the end of the deck */
80+
iter->next = newDeckNode;
81+
iter = iter->next;
82+
/* iterate thru pile of cards*/
83+
iter2 = iter2->next;
84+
}
85+
}
86+
87+
88+
/**
89+
* @brief Taking all cards back from piles and make them in one deck
90+
* @param[in] pilesInUse: piles that currently have cards
91+
* @return pointer to deck_t, which holds all cards taken from all piles
92+
*/
93+
static deck_t* makeDeck(int pilesInUse)
94+
{
95+
96+
deck_t* retDeck = (deck_t*)malloc(sizeof(deck_t));
97+
//first node in deck is dummy node, real code starts at second node
98+
retDeck->val = -1;
99+
retDeck->next = NULL;
100+
101+
/* Link all piles together */
102+
for(int i = 0; i < pilesInUse; i++){
103+
addToDeckTail(&pileArr[i], retDeck);
104+
}
105+
106+
return retDeck;
107+
}
108+
109+
/**
110+
* @brief add to the front of the pile
111+
* @param[in/out] pile pile needs to be added
112+
* @param[in] cal card val
113+
*/
114+
static void addToPileFront(pile_t* pile, int val)
115+
{
116+
card_t* newCard = (card_t*)malloc(sizeof(card_t));
117+
newCard->val = val;
118+
if(pile->top_card->val == -1){
119+
pile->top_card = newCard;
120+
return;
121+
}
122+
newCard->next = pile->top_card;
123+
pile->top_card = newCard;
124+
}
125+
126+
/**
127+
* @brief Taking cards from current deck and distribute it back to piles
128+
the cards will be updated by modifying pileArr
129+
* @param[in] pilesInUse piles that currently have cards
130+
* @param[in] deck deck holding cards needs to be distributed
131+
*/
132+
static void distribute(int pilesInUse, deck_t* deck)
133+
{
134+
deck_t* deckIter = deck;
135+
uint8_t pileInd = 0;
136+
137+
while(deckIter){
138+
if(deckIter->val == -1){
139+
deckIter = deckIter->next;
140+
continue;
141+
}
142+
addToPileFront(&pileArr[pileInd],deckIter->val);
143+
deckIter = deckIter->next;
144+
pileInd = (pileInd+1)%pilesInUse;
145+
}
146+
}
147+
148+
149+
/**
150+
* @brief given a card value add it to the deck
151+
* @param [in] val card value
152+
* @param[in/out] deck needs to be added with cards
153+
*/
154+
static deck_t* addToDeckTail2(int val, deck_t* deck)
155+
{
156+
deck_t* newVal = (deck_t*)malloc(sizeof(deck_t));
157+
newVal->val = val;
158+
newVal->next = NULL;
159+
if(deck->val == -1){
160+
deck = newVal;
161+
return deck;
162+
}
163+
164+
/* Find last one in current deck */
165+
deck_t* iter = deck;
166+
while(iter->next){
167+
iter = iter->next;
168+
}
169+
iter->next=newVal;
170+
return deck;
171+
}
172+
173+
/**
174+
* @brief printout all the cards in the deck
175+
*
176+
* @param[in] deckIn pointer to deck_t
177+
*/
178+
static void printDeck(deck_t* deckIn)
179+
{
180+
if(!deckIn){
181+
printf("empty deck\n");
182+
return;
183+
}
184+
185+
deck_t* iter = deckIn;
186+
while(iter){
187+
if(iter->val != -1)
188+
printf("%d ", iter->val);
189+
iter = iter->next;
190+
}
191+
printf("\n");
192+
}
193+
194+
195+
/**
196+
* @brief check current check order and return true
197+
* if it is original order(0,1,2,3......numCards)
198+
* @param[in] deck the pointer to deck
199+
* @return true if ir is original order
200+
*/
201+
static bool checkOrder(deck_t* deck)
202+
{
203+
deck_t* iter = deck;
204+
int prev;
205+
prev = iter->val;
206+
iter = iter->next;
207+
208+
while(iter){
209+
if(prev!= (iter->val)-1)
210+
return false;
211+
prev = iter->val;
212+
iter = iter->next;
213+
}
214+
return true;
215+
}
216+
217+
int main(int argv, char**argc)
218+
{
219+
if(argv != 2){
220+
printf("Please try again!\n");
221+
printf("Usage: ./<out file name> <number of cards>\n");
222+
return 0;
223+
}
224+
int numCards = atoi(argc[1]);
225+
226+
deck_t* deck = (deck_t*)malloc(sizeof(deck_t));
227+
deck->val = -1;
228+
229+
/* global data init */
230+
for(int i = 0; i < MAX_TOTAL_PILES; i++){
231+
card_t* newCard = (card_t*)malloc(sizeof(card_t));
232+
pileArr[i].top_card = newCard;
233+
pileArr[i].top_card->val = -1;
234+
}
235+
236+
/* initialize first deck */
237+
for(int i = 0; i < numCards; i++){
238+
deck = addToDeckTail2(i, deck);
239+
}
240+
printf("original deck order:\n");
241+
242+
243+
244+
bool originalOrder = false;
245+
int numRounds = 0;
246+
int pileNumInd = 0;
247+
deck_t* curr_deck = deck;
248+
printf("original deck order:\n");
249+
printDeck(curr_deck);
250+
251+
/* Driver logic: repeatively distribute cards into piles and taken them back
252+
untill original order is restored */
253+
while(!originalOrder){
254+
255+
distribute(pileNumberTable[pileNumInd], curr_deck);
256+
257+
curr_deck = makeDeck(pileNumberTable[pileNumInd]);
258+
259+
printf("Current deck order:\n");
260+
printDeck(curr_deck);
261+
262+
resetPiles();
263+
264+
originalOrder = checkOrder(curr_deck);
265+
266+
numRounds++;
267+
pileNumInd = (pileNumInd+1)%NUM_PILES;
268+
}
269+
270+
printf("Total round needed: %d\n", numRounds);
271+
return 0;
272+
}
273+
274+
275+
276+
/* Bonus Question: */
277+
278+
/**
279+
It would really depends on the detailed meaning&defenition of "shuffleness", given a clear defenition
280+
of "ramdomness", for eg. some stats relationnship for each adjacent elements, we can computer them and
281+
see if the "adequate shuffleness has been reached and make a note of that."
282+
*/
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
Question 2
3+
4+
A fellow developer has asked you to review the following code. Please
5+
provide your feedback:
6+
*/
7+
8+
9+
#include <stdlib.h>
10+
#include <stdint.h>
11+
#include <stdio.h>
12+
#include <string.h>
13+
14+
//Cong: For comments made by Cong Jin will have a tag: "Cong"*/
15+
16+
/*
17+
* This is a circular buffer that allows enqueue or dequeue arbitrary
18+
* amount of bytes. The buffer size is limited to BUF_SIZE.
19+
*/
20+
21+
static char *GetErrorString(int x);
22+
23+
#define BUF_SIZE 4096 //Cong: can wrap the constant with ()
24+
25+
typedef struct {
26+
int write_index; //can use uint32_t
27+
int read_index; //can use uint32_t
28+
char *buf;
29+
int size; //can use size_t or uint32_t
30+
} circular_buf_t;
31+
32+
circular_buf_t buf;
33+
34+
/*
35+
* Enqueue (size) bytes from (client_buf) to the local buf
36+
* memory of (client_buf) is allocated by the caller
37+
*/
38+
int enqueue(char *client_buf, int size)
39+
{
40+
if (size > BUF_SIZE) {
41+
printf("%s", GetErrorString(3)); //Should be 2 overflow case
42+
return 3; //Cong: can #define error code for better logging/debugging
43+
}
44+
45+
int part1 = buf.size - buf.write_index;
46+
memcpy(client_buf, buf.buf + buf.write_index, part1);
47+
48+
if (part1 != size) { //Cong: condition should be part1 < size, so that we need to continue wrapping the buf and copy the rest
49+
int part2 = size - part1;//Cong: part2 should take care read_index, since this is where data is still not popped, shoud be size-part1-read_index
50+
memcpy(client_buf+part1, buf.buf[0], part2);
51+
}
52+
53+
return 0;
54+
}
55+
56+
/*
57+
* Dequeue (size) bytes from the local buf to (client_buf),
58+
* (client_buf) is allocated by the caller. It is okay to assume
59+
* (client_buf) is big enough to hold all the (size) bytes
60+
*/
61+
int dequeue(char *client_buf, int size)
62+
{
63+
if (size < BUF_SIZE) { //Cong: size > BUF_SIZE for overflow condition?
64+
printf("%s", GetErrorString(2));
65+
return 2;
66+
}
67+
68+
int copy_size = buf.write_index - buf.read_index + 1;
69+
//Cong: size should be taken int account when assigned actual copy size:
70+
//copy_size = size <= copy_size ? size : copy_size;
71+
memcpy(client_buf, buf.buf + buf.write_index, copy_size); //Cong: should dequeue from buf.buf+buf.read_index
72+
73+
return 0;
74+
}
75+
76+
//Cong: Personally recommand to put all static funtion at the top
77+
static char *GetErrorString(int x)
78+
{
79+
char errorString[20]; //Can #define the max error string
80+
81+
switch ( x )
82+
{
83+
case 0:
84+
errorString = "Success -- No error.";
85+
break;
86+
case 2:
87+
errorString = "Overflow!";
88+
break;
89+
//Cong: there is no default case and case 3 handling is not specified
90+
}
91+
92+
errorString[19] = 0;//Cong '\0' for terminating the array?
93+
return errorString;
94+
}
95+
96+
97+
int main(int argc,char* argv[])
98+
{
99+
// initialize buffer
100+
buf.buf = malloc(BUF_SIZE); //Cong: 1.better to typecase the return of malloc 2. better to do BUF_SIZE*sizeof(char)
101+
//Cong: need to check if malloc is returning null pointer due to OOM and do error handling
102+
buf.size = BUF_SIZE;
103+
//Cong: Also need to initialize read_index and write_index for intialization
104+
105+
// Perform enqueue() and dequeue();
106+
107+
// All completed, return
108+
return 0;
109+
}
File renamed without changes.

0 commit comments

Comments
 (0)