问:
C programming linked list and queue with an array
I need to enqueue a whole struct customer in the queue - I think. This is my homework. I am not asking for an answer. I need a mentor to explain what I am missing and what I have right per the assignment. I am very new. This is my second program. see below... thanks btw.

A store is having customers queue in several lines. After the cashier finishes helping a customer, he will survey all of the lines that are currently queued. Of all of the customers at the front of those lines, he’ll take the customer who has the fewest number of items. If there are two customers with the same number of items, he’ll take the customer who comes from the smaller line number. The lines are numbered 1 through 12. It’s possible that some of these lines will be empty, in which case these lines are ignored. The number of seconds the store clerk takes to check out a customer is 30 plus 5 times the number of items. Thus, if a customer has 8 times, the clerk would check her out in 30 + 8*5 = 70 seconds.
The Problem
You will write a program that reads in information about customers: which line they go to the back of (1 through 12), at what time (in seconds) they enter that line, and the number of items they have, and determines at what time each customer will check out.

Sample Input:

```<code>2

5
10 1 STEVEN 12
12 6 AHMAD 8
13 1 JENNY 40
22 6 JERMAINE 39
100000 12 AMALIA 53

6
100 1 A 100
200 2 B 99
300 3 C 98
400 4 D 97
500 5 E 96
600 6 F 95
</code>```

Sample Output:

```<code>STEVEN from line 1 checks out at time 100.
AHMAD from line 6 checks out at time 170.
JERMAINE from line 6 checks out at time 395.
JENNY from line 1 checks out at time 625.
AMALIA from line 12 checks out at time 100295.

A from line 1 checks out at time 630.
F from line 6 checks out at time 1135.
E from line 5 checks out at time 1645.
D from line 4 checks out at time 2160.
C from line 3 checks out at time 2680.
B from line 2 checks out at time 3205.
</code>```

Implementation Restrictions:

You must create a struct that stores information about a customer (name, number of items, line number, time entering line). Note that the storage of the line number is redundant, but is designed to ease implementation.

You must create a node struct for a linked list of customers. This struct should have a pointer to a customer struct, and a pointer to a node struct.

You must create a struct to store a queue of customers. This struct should have two pointers – one to the front of the queue and one to the back.

You must implement all of the lines that form as an array of size 12 (stored as a constant) of queues.

You must dynamically allocate memory as appropriate for linked lists.

Your queue must support the following operations:
a. Enqueue
b. Dequeue
c. Return the front of the queue WITHOUT dequeing d. Empty (returns 1 if the queue is empty, 0 if it is not)

You must free memory appropriately. Namely, when you dequeue, you’ll free memory for a node, but you will NOT free memory for the customer. You will free this memory a bit later right after you calculate when that customer will finish checking out.

Due to the nature of the problem, when you process the input, you can add everyone into their appropriate lines right at the beginning, before checking anyone out.

This wouldn’t work in all simulations (some of which you have to do in time order), but because there is ONLY one check out line, you can get away with it. The only thing you have to be cognizant about is that when you select a line, if the current time is, 100 for example, and three lines have customers who arrived before time 100 and the other lines have customers in the front who arrived AFTER time 100, you have to ignore the customers in those lines who arrived after time 100. In the case that all the lines have customers who arrived after time 100, you would take the line which has a customer who arrived first. You are guaranteed no ties for arrival time so this would be unique.

```<code>#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define TRUE 1
#define FALSE 0

typedef char customerName[9];

typedef struct node
{
    int data;
    struct node *next;
}node;

typedef struct queue
{
    int size;
    int front;
    int back;
    int *array;
    unsigned capacity;

}queue;

typedef struct customer
{
    customerName name;//1-9 upper case letters
    int lineNumber;
    int time;
    int numberItems;
} customer;

int isEmpty(queue *q);
void initialize(queue *q);

void initialize(queue *q)
{
    q->size = 0;
    q->front = -1;
    q->back = -1;
}

int isEmpty(queue *q){
    return (q->size == 0);//returns 1 if empty or 0 if false
}

int isFull(queue *q)
{  return (q->size == q->capacity);  }

void enqueue(queue *q, int item)
{
    if (isFull(q))
        return;
    q->back = (q->back + 1)%q->capacity;
    q->array[q->back] = item;
    q->size = q->size + 1;
}

int dequeue(queue *q)
{
    if (isEmpty(q))
        return 0;
    int item = q->array[q->front];
    q->front = (q->front + 1)%q->capacity;
    q->size = q->size - 1;
    return item;
}

int front(queue* q){
    if(isEmpty(q)){
        return 0;
    }
    return q->array[q->front];
}

int main(int argc, const char * argv[]) {

    int testCases = 0;
    scanf("%d", &testCases);

    if(testCases > 0 && testCases <= 25){//shortcircuiting???

    while (testCases--){

        queue *q;
        q = malloc(sizeof(queue));
        initialize(q);// starting new queue

        int numCustomers;
        scanf("%d", &numCustomers);

        if(numCustomers < 0 || numCustomers > 11){
            return 0;
        }

        struct customer newCustomer[1];

        for ( int i = 0; i < numCustomers; i++){
            scanf("%d", &newCustomer[i].time);
            scanf("%d", &newCustomer[i].lineNumber);
            scanf("%s", newCustomer[i].name);
            scanf("%d", &newCustomer[i].numberItems);
            enqueue(q, newCustomer[i].time);
            enqueue(q, newCustomer[i].lineNumber);

        }

        for ( int i = 0; i < numCustomers; i++){
            printf("%d %d %s %d\n", newCustomer[i].time, newCustomer[i].lineNumber, newCustomer[i].name, newCustomer[i].numberItems);

               }

    }
}
    return 0;
}
</code>```

Here is my latest code:

```<code>#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define TRUE 1
#define FALSE 0
#define NUMLINES 12
int currtime = 0;

typedef char customerName[9];

typedef struct node
{
    int data;
    struct customer* data;
    struct node* next;

}node;

typedef struct queue
{
    node* front;
    node* back;
}queue;

typedef struct customer
{
    customerName name;//1-9 upper case letters
    int lineNumber;
    int time;
    int numberItems;
} customer;

typedef struct node *newNode;//define a node pointer

node createNode()
{
    newNode temp;//declare node
    temp = (newNode)malloc(sizeof(struct node));//allocate memory
    temp->next = NULL;//next point to null
    return *temp;// return the new node

}

struct queue* createQueue()
{
    struct queue* q = (struct queue*)malloc(sizeof(struct queue));
    q->front = q->back = NULL;
    return q;
}

int isEmpty(queue *q){
    return (q->back == NULL);//returns 1 if empty or 0 if false
}

void enqueue(queue *q, customer* data)
{
        // Create a new LL node
       struct node* temp = createNode(data);

       // If queue is empty, then new node is front and back both
       if (q->back == NULL) {
           q->front = q->back = temp;
           return;
       }

       // Add the new node at the end of queue and change back
       q->back->next = temp;
       q->back = temp;
}

void dequeue(queue *q)
{
     if (q->front == NULL)
           return;

       // Store previous front and move front one node ahead
       struct node* temp = q->front;
       q->front = q->front->next;

       // If front becomes NULL, then change rear also as NULL
       if (q->front == NULL)
           q->back = NULL;

       free(temp);
}

int front(queue* q){
    if(isEmpty(q)){
        return 0;
    }
    return q->front;
}

int main(int argc, const char * argv[]) {

    int testCases = 0;
    scanf("%d", &testCases);

    if(testCases > 0 && testCases <= 25){//shortcircuiting???

    while (testCases--){

        queue *q;
        q = malloc(sizeof(queue));
        initialize(q);// starting new queue

        int numCustomers;
        scanf("%d", &numCustomers);

        if(numCustomers < 0 || numCustomers > 11){
            return 0;
        }

        struct customer newCustomer[11];

        for ( int i = 0; i < numCustomers; i++){
            scanf("%d", &newCustomer[i].time);
            scanf("%d", &newCustomer[i].lineNumber);
            scanf("%s", newCustomer[i].name);
            scanf("%d", &newCustomer[i].numberItems);
            enqueue(q, newCustomer[i].time);
            enqueue(q, newCustomer[i].lineNumber);

        }

        for ( int i = 0; i < numCustomers; i++){
            printf("%d %d %s %d\n", newCustomer[i].time, newCustomer[i].lineNumber, newCustomer[i].name, newCustomer[i].numberItems);

               }

    }
}
    return 0;
}
</code>```

```<code>int main(int argc, const char * argv[]) {

    int testCases = 0;
    scanf("%d", &testCases);

    if(testCases > 0 && testCases <= 25){//shortcircuiting???

    while (testCases--){

        queue *q;
        q = malloc(sizeof(queue));
        qinit(q);// starting new queue

        int numCustomers;
        scanf("%d", &numCustomers);

        if(numCustomers < 0 || numCustomers > 11){
            return 0;
        }

        queue* customerArray = (queue*) malloc(sizeof(queue) * 12);

        for ( int i = 0; i < numCustomers; i++){

            customer* newCustomer = (customer*) malloc(sizeof(customer));

            scanf("%d", &(newCustomer->time));
            scanf("%d", &(newCustomer->lineNumber));
            scanf("%s", newCustomer->name);
            scanf("%d", &(newCustomer->numberItems));
            enqueue(&customerArray[newCustomer->lineNumber - 1], newCustomer);
        }

        int totalTime = INT_MAX;

        for(int i=0;i<12;i++)
        {
        customer* frontCustomer = qfront(&customerArray[i]);
         if(totalTime < frontCustomer->time)
            {
                totalTime = frontCustomer->time;
            }
            free(frontCustomer);
         }

       while(numCustomers--) {

           int customerToCheckOutLine = 0; int minNumberOfItems = INT_MAX;

        for( int j=11 ; j>=0; j--){

            customer* frontCustomer = qfront(&customerArray[j]);
            if(frontCustomer->time <= totalTime)
            {
                if(frontCustomer->numberItems < minNumberOfItems)
                {
                    customerToCheckOutLine = frontCustomer->lineNumber;
                    minNumberOfItems = frontCustomer->numberItems;
                }
                free(frontCustomer);
            }
        }

        customer* customerToCheckOut = qfront(&customerArray[customerToCheckOutLine -1 ]);
        totalTime += 30;
        totalTime += (customerToCheckOut->numberItems) * 5;
           dequeue(&customerArray[customerToCheckOutLine - 1]);
       }
        free(customerArray);

    }
}
    return 0;
}
</code>```

答:
Your queue related functions look okay.

But, there are some bugs and the code needs refactoring to handle more things.

Your queue element array should be of type node * instead of int *.

You need the newCustomer array to be of length numCustomers (i.e. not 1).

At present, you have a single queue. But, you need an array of queues, one for each line, so an array length of 12.

When you queue a customer, you must select the queue [from the array of queues] based on the line number the customer is getting on.

Here's a biggie:

You can't queue two separate entries, one being time and the other being lineNumber. Well, you can I guess, but it's messy.

The way I'd do it is to change the data element of the node struct to be a pointer to the customer record. That way, every bit of data you need to determine the servicing order is [already] in the customer struct.

Anyway, here's some refactored code.

Per your request, it's not a solution, but some sample code as a basis for implementing the above fixes/suggestions.

You still have to change the queue struct and all queue related functions (if you decide to change the struct as I've suggested).

And, you still have to implement the selection/ordering process. And, the cleanup/deallocation.

This won't compile as is, because it's a "suggestion", but here it is:

```<code> typedef char customerName[9];

typedef struct customer {
    customerName name;                  // 1-9 upper case letters
    int lineNumber;
    int time;
    int numberItems;
} customer;

typedef struct node {
#if 0
    int data;
#else
    customer *data;
#endif
    struct node *next;
} node;

typedef struct queue {
    int size;
    int front;
    int back;
#if 0
    int *array;
#else
    node *array;
#endif
    unsigned capacity;
} queue;

#if 1
#define NUMLINES        12
queue queue_list[NUMLINES];
#endif

int isEmpty(queue *q);
void initialize(queue * q);

void
initialize(queue *q)
{
    q->size = 0;
    q->front = -1;
    q->back = -1;
}

int
isEmpty(queue *q)
{
    return (q->size == 0);              // returns 1 if empty or 0 if false
}

int
isFull(queue *q)
{
    return (q->size == q->capacity);
}

void
enqueue(queue *q, int item)
{
    if (isFull(q))
        return;
    q->back = (q->back + 1) % q->capacity;
    q->array[q->back] = item;
    q->size = q->size + 1;
}

int
dequeue(queue *q)
{
    if (isEmpty(q))
        return 0;
    int item = q->array[q->front];

    q->front = (q->front + 1) % q->capacity;
    q->size = q->size - 1;
    return item;
}

int
front(queue *q)
{
    if (isEmpty(q)) {
        return 0;
    }
    return q->array[q->front];
}

int
main(int argc, const char *argv[])
{
    queue *q;

    int testCases = 0;

    scanf(" %d", &testCases);

    // NOTE/BUG: you need a separate queue for each line
    for (int qidx = 0;  qidx < NUMLINES;  ++qidx) {
        q = &queue_list[qidx];
        initialize(q);
    }

    // shortcircuiting???
    if (testCases > 0 && testCases <= 25) {
        while (testCases--) {
#if 0
            queue *q;
#endif

#if 0
            q = malloc(sizeof(queue));
            initialize(q);              // starting new queue
#endif

            int numCustomers;

            scanf(" %d", &numCustomers);

            if (numCustomers < 0 || numCustomers > 11) {
                return 0;
            }

            // NOTE/BUG: you need a larger array of customers
#if 0
            struct customer newCustomer[1];
#else
            struct customer newCustomer[numCustomers];
#endif

            for (int i = 0; i < numCustomers; i++) {
                customer *cust = &newCustomer[i];

                scanf(" %d", &cust->time);
                scanf(" %d", &cust->lineNumber);
                scanf(" %s", cust->name);
                scanf(" %d", &cust->numberItems);

                // NOTE/BUG: customer must be queued to the queue for the
                // line number they're on
                // NOTE/BUG: queue a single entry for each customer
#if 0
                enqueue(q, cust->time);
                enqueue(q, cust->lineNumber);
#else
                q = &queue_list[cust->lineNumber - 1];
                enqueue(q,cust);
#endif
            }

            for (int i = 0; i < numCustomers; i++) {
                printf("%d %d %s %d\n",
                    newCustomer[i].time,
                    newCustomer[i].lineNumber,
                    newCustomer[i].name,
                    newCustomer[i].numberItems);
            }
        }
    }

    return 0;
}
</code>```

UPDATE:

woah, this is amaze balls. thank you so much. I think the assignment is confusing because he says the assignment is queues with linked list not an array but like you said it needs to be an array of queues. that would suggest multiple entries into a single line. so in a sense this is both an queues with linked lists and array?

You need an array of queues, indexed by linenumber. This is not to be confused with the q->array element within the queue, which is different.

I just completed a working and tested version [for myself, because I'm crazy that way :-)]. I had the same confusion.

The queue is a ring queue [with array]. If the array pointer is a customer *, I couldn't find a good way to use node. The only way to do it would be to convert queue into a linked list header struct. That would require queue to be restructured [along will all the access functions for it ;-)].

But, before doing that, if we keep the array/ring method, then initialize needs to take a capacity arg (called with initialize(q,numCustomer);). And, it needs to do (e.g.) q->array = realloc(q->array,sizeof(customer *) * capacity);

And, enqueue needs a fix: the increment of q->back needs to be moved after the q->array[q->back] = item;. Currently, there is an off by one gap.

To convert to a linked list:

The structs change a bit:

```<code>typedef struct node {
    customer *data;
    struct node *next;
} node;

typedef struct queue {
    node *front;
} queue;
</code>```

You have an isFull function. That's not part of the requirements. If we switch queue into a linked list header for a list of node, it isn't even relevant/meaningful since, now, there is no maximum [as there was with q->capacity].

Now, when doing enqueue(q,cust);, the function would malloc a new node and append it to the end of the linked list. And, setup of (e.g.) newnode->next and newnode->data = cust;

When doing dequeue, it pops off the front element (a node), does cust = curnode->data;, then free(curnode), and returns cust.

Based on my rereading the requirements, I believe that this is what's required, and actually makes sense of all of them.

In other words, you can implement a queue with just a linked list (vs. what you did which was a ring queue with array--which I've also done in the past).

the ordering process is part of the reason I am so confused. I don't know where to do this. The list is already ordered by time the customer went to check out. I just need to calculate the total cashier time.there is only one cashier so all the people are served in order of entering the queue.

This is a bit tricky. You have to have a curtime global to keep track of the current time. Initially, this has to be set to the minimum of all cust->time values.

As you loop through all queues [i.e. waiting lines] to look at the first customer on the line, you have to do the following:

You skip the queue if it's empty.

You skip any customer if they have an arrival date in the future (i.e. cust->time > curtime).

Now you can "select" the customer. You need the find "best" customer [for the next one to be serviced]. That is, the one with the smallest order. The 2nd criteria of: with a tie, the customer with the lowest line number wins is handled automatically if you only update the "best" value if (cust->numberItems < best->numberItems) because we're traversing the queue_list array from low to high.

Then, service the "best" customer (i.e. print the message). Then, increment curtime by the elapsed time it takes to service the customer.

Repeat this until all queues are empty.

But, there is one gotcha. It happens with AMALIA.

The arrival time for this customer is so far in the future that the customer selection will fail to find any "best" customer because amalia->time is greater than curtime. Thus, it seems like AMALIA is not ready to be serviced.

So, if the selection fails (i.e. best is null), we have to loop through all front customers [again] and set curtime to the minimum of all their arrival times.

Then, we rescan/reselect for "best". Now, AMALIA will be selected

UPDATE #2:

in your example I don't understand what the #elseif etc. what are those? other than the obvious, I have never seen this

The lines starting with #if are preprocessor statements [just like #include, #ifdef, #else, #endif

The preprocessor is used to include/exclude code at compile time (vs using a real if language statement). You can think of the preprocessor as a separate pass before compilation that performs the conditional actions before passing the resultant file to the compile stage.

In my examples, I'm using them to show old code [yours] vs. new code [mine]:

```<code>#if 0
    // old code ...
    x = 1;
#else
    // new code ...
    x = 2;
#endif
</code>```

When compiled, the old code is excluded, the new code is included as if we had done:

```<code>    // new code ...
    x = 2;
</code>```

This is a useful technique in general. It allows you to "comment out" code that you suspect might be a bug. Or, for debug printf code. Or, you have working code (the "old" code), but you want to try something possibly cleaner or more efficient (the "new" code). You can flip back and forth during development just by changing #if 0 to #if 1 or vice versa

You can see the intermediate file by doing:

```<code>cc -E -P -o myfile.i myfile.c
</code>```

Later on, when your code is [fully ;-)] debugged, you could hand edit out the #if cases you don't need/want.

can you do that same kind of example but for the linked list only implementation? or is that asking too much? :) why is there only a *front and no back of the list?

For a simple singly linked list, we only truly need a head/front pointer.

We don't need size because the empty case is: q->front == NULL. size is primarily useful if we had to sort the linked list (it saves a pass on the list to get the number of elements).

Using q->back adds a slight degree of complexity. It's a speedup when appending to the queue/list. If we don't have it, we find the last element in the list by traversing it. If we have back, that is the last element.

A singly linked list is sufficient for your use case. But, just for completeness, I've added doubly linked list support. We add a prev element to node [the backwards link].

Below, I've coded up the linked list structs and functions. To allow you to see the various modes, each optional element is wrapped in preprocessor #if/#endif pairs to include/exclude code, based on setting the given option on/off

DLINK [doubly linked list] is off by default

To enable it on a one time basis, you could do:

```<code>cc -DDLINK=1 -c myfile.c
</code>```

Likewise for other options.

Anyway, here's the queue code based on a linked list:

```<code>// customer record
typedef char customerName[9];
typedef struct customer {
    customerName name;                  // 1-9 upper case letters
    int lineNumber;                     // line number customer gets on
    int time;                           // arrival time at line
    int numberItems;                    // number of items customer has
} customer;

// 1=use queue q->back
// need this for _doubly_ linked list
// speedup for append to end of queue for singly linked
#ifndef QBACK
#define QBACK       1
#endif

// 1=use queue q->size
#ifndef QSIZE
#define QSIZE       1
#endif

// 1=use doubly linked list
#ifndef DLINK
#define DLINK       0
#endif

// force QBACK on if doing doubly linked list
#if DLINK
#undef QBACK
#define QBACK       1
#endif

// [singly linked] queue element
typedef customer *qitem;
typedef struct node {
    qitem data;                         // pointer to actual data
    struct node *next;                  // forward pointer to next item
#if DLINK
    struct node *prev;                  // backward pointer to previous item
#endif
} node;

// queue definition (singly linked list)
// NOTE:
typedef struct queue {
    node *front;                        // pointer to first node in list
#if QBACK
    node *back;                         // pointer to last node in list
#endif
#if QSIZE
    int size;                           // current number of elements in list
#endif
} queue;

// list of queues (indexed by lineNumber - 1)
#define NUMLINES        12
queue queue_list[NUMLINES];

// qinit -- initialize/reset queue
void
qinit(queue *q)
{

    q->front = NULL;

#if QSIZE
    q->size = 0;
#endif

#if QBACK
    q->back = NULL;
#endif
}

// qempty -- returns 1 if empty or 0 if false
int
qempty(queue *q)
{
    // NOTE: size really isn't needed
#if 0
    return (q->size == 0);
#else
    return (q->front == NULL);
#endif
}

// enqueue -- append element to end of queue
void
enqueue(queue *q, qitem data)
{
    node *newnode;
    node *prev;

    newnode = malloc(sizeof(node));
    newnode->next = NULL;
    newnode->data = data;

    // NOTE: this is the only place where back is a speedup
#if QBACK
    prev = q->back;
#else
    // what we have to do find the back of the queue with only a front pointer
    prev = NULL;
    for (node *cur = q->front;  cur != NULL;  cur = cur->next)
        prev = cur;
#endif

    // append to tail of list
    if (prev != NULL)
        prev->next = newnode;

    // add to end of empty list
    else
        q->front = newnode;

#if DLINK
    newnode->prev = prev;
#endif

#if QBACK
    q->back = newnode;
#endif

#if QSIZE
    q->size += 1;
#endif
}

// dequeue -- dequeue from the front of the queue
qitem
dequeue(queue *q)
{
    node *curnode;
    qitem data;

    do {
        curnode = q->front;

        // bug out if list is empty
        if (curnode == NULL) {
            data = NULL;
            break;
        }

        // get node's data value (e.g. pointer to customer struct)
        data = curnode->data;

#if QBACK
        node *back = q->back;
#if DLINK
        curnode->prev = back;
#endif
        if (curnode == back)
            q->back = curnode->next;
#endif

        q->front = curnode->next;

#if QSIZE
        q->size -= 1;
#endif

        // release the node's storage back to the heap
        free(curnode);
    } while (0);

    return data;
}

// qfront -- peek at front of queue
qitem
qfront(queue *q)
{
    node *curnode;
    qitem data;

    curnode = q->front;
    if (curnode != NULL)
        data = curnode->data;
    else
        data = NULL;

    return data;
}
</code>```

UPDATE #3:

so my main function has a memory leak and I cannot find it. I am trying to learn Valgrind and gdb but there is a learning curve. My Valgrind outran is like 90,000 characters for some reason and doesn't say hey I have a memory leak. I don't even know what line. I appended my new main to the bottom of the above code.

A few issues:

You malloc the q pointer at the top of the outer while (testCases--) loop but do not free it.

But, as I mentioned, you need an array of queues [which can be a fixed array] and you've already done that.

But, q was your original/legacy code. The rest of your code no longer uses q. You just forgot to remove it.

You are now using customerArray instead. But, you are not calling qinit on each array element, so you could have a random data in each.

In the problem definition, the number of customer lines is fixed at 12, so you really don't need to malloc and free it. That's why I used a global array instead.

You have a bug in your totalTime calculation loop. You're doing a free of the customer record. So, the record is no longer valid in the loop below it.

And, in that second loop, you're doing a second free of the same struct. So, at present, this is a "double free" bug. The second loop is actually the correct place for the free [not the first loop]

This program is ambitious for a second ever assignment, so you're "being thrown out into the middle of the lake and being asked to swim to shore".

I would have expected a few more intermediate steps/programs before trying to code up this one.

When starting out, as you are, sometimes it's as important to study working code as it is to write it from scratch.

So, spoiler alert, here's my final, fully working code:

```<code>#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define TIME_PAST       -1              // infinite time in the past
#define TIME_FUTURE     INT_MAX         // infinite time in the future
int curtime;                            // current time

// customer record
typedef char customerName[9];
typedef struct customer {
    customerName name;                  // 1-9 upper case letters
    int lineNumber;                     // line number customer gets on
    int time;                           // arrival time at line
    int numberItems;                    // number of items customer has
} customer;

// 1=use queue q->back
// need this for _doubly_ linked list
// speedup for append to end of queue for singly linked
#ifndef QBACK
#define QBACK       1
#endif

// 1=use queue q->size
#ifndef QSIZE
#define QSIZE       1
#endif

// 1=use doubly linked list
#ifndef DLINK
#define DLINK       0
#endif

// force QBACK on if doing doubly linked list
#if DLINK
#undef QBACK
#define QBACK       1
#endif

// [singly linked] queue element
typedef customer *qitem;
typedef struct node {
    qitem data;                         // pointer to actual data
    struct node *next;                  // forward pointer to next item
#if DLINK
    struct node *prev;                  // backward pointer to previous item
#endif
} node;

// queue definition (singly linked list)
// NOTE:
typedef struct queue {
    node *front;                        // pointer to first node in list
#if QBACK
    node *back;                         // pointer to last node in list
#endif
#if QSIZE
    int size;                           // current number of elements in list
#endif
} queue;

// list of queues (indexed by lineNumber - 1)
#define NUMLINES        12
queue queue_list[NUMLINES];

// qinit -- initialize/reset queue
void
qinit(queue *q)
{

    q->front = NULL;

#if QSIZE
    q->size = 0;
#endif

#if QBACK
    q->back = NULL;
#endif
}

// qempty -- returns 1 if empty or 0 if false
int
qempty(queue *q)
{
    // NOTE: size really isn't needed
#if 0
    return (q->size == 0);
#else
    return (q->front == NULL);
#endif
}

// enqueue -- append element to end of queue
void
enqueue(queue *q, qitem data)
{
    node *newnode;
    node *prev;

    newnode = malloc(sizeof(node));
    newnode->next = NULL;
    newnode->data = data;

    // NOTE: this is the only place where back is a speedup
#if QBACK
    prev = q->back;
#else
    // what we have to do find the back of the queue with only a front pointer
    prev = NULL;
    for (node *cur = q->front;  cur != NULL;  cur = cur->next)
        prev = cur;
#endif

    if (prev != NULL)
        prev->next = newnode;
    else
        q->front = newnode;

#if DLINK
    newnode->prev = prev;
#endif

#if QBACK
    q->back = newnode;
#endif

#if QSIZE
    q->size += 1;
#endif
}

// dequeue -- dequeue from the front of the queue
qitem
dequeue(queue *q)
{
    node *curnode;
    node *nextnode;
    qitem data;

    do {
        // get the first node
        curnode = q->front;

        // if none, return null data
        if (curnode == NULL) {
            data = NULL;
            break;
        }

        // get the data payload
        data = curnode->data;

        // point to the next node (i.e. second node)
        nextnode = curnode->next;

#if QBACK
        node *back = q->back;
#if DLINK
        curnode->prev = back;
#endif
        if (curnode == back)
            q->back = nextnode;
#endif

        q->front = nextnode;

#if QSIZE
        q->size -= 1;
#endif

        free(curnode);
    } while (0);

    return data;
}

// qfront -- peek at front of queue
qitem
qfront(queue *q)
{
    node *curnode;
    qitem data;

    curnode = q->front;
    if (curnode != NULL)
        data = curnode->data;
    else
        data = NULL;

    return data;
}

// custfind -- find next customer to serve
customer *
custfind(void)
{
    int pass;
    int qidx;
    queue *q;
    int mintime;
    int moreflg;
    customer *cust;
    customer *best;

    // pass 1:
    // - remember the minimum time
    // - find best using curtime
    for (pass = 1;  pass <= 2;  ++pass) {
        best = NULL;
        mintime = TIME_FUTURE;
        moreflg = 0;

        // scan all queues -- examine _first_ customer on each line
        for (qidx = 0;  qidx < NUMLINES;  ++qidx) {
            q = &queue_list[qidx];

            // get first customer on current line
            cust = qfront(q);
            if (cust == NULL)
                continue;

            // remember that there is at least _one_ customer waiting
            moreflg = 1;

            // remember the minimum time
            if (cust->time < mintime)
                mintime = cust->time;

            // has the customer actually arrived yet? -- skip if not
            if (cust->time > curtime)
                continue;

            // no previous "best" customer -- set from current
            if (best == NULL) {
                best = cust;
                continue;
            }

            // get better customer (has fewer items to check out)
            if (cust->numberItems < best->numberItems) {
                best = cust;
                continue;
            }
        }

        // no more customers
        if (! moreflg)
            break;

        // found a best match
        // dequeue and free node
        if (best != NULL) {
            q = &queue_list[best->lineNumber - 1];
            dequeue(q);
            break;
        }

        // no best match found
        // all customers are in the future [based on curtime]
        // set new current time based on minimum time of all remaining customers
        // the second pass _will_ find at least one after we do this
        curtime = mintime;
    }

    return best;
}

// custdo -- check out customer
void
custdo(customer *cust)
{
    int elap;

    // current time has to be _at least_ the arrival time
    if (curtime < cust->time)
        curtime = cust->time;

    // get amount of time it takes to service this customer
    elap = 0;
    elap += 30;
    elap += cust->numberItems * 5;

    // set current time after servicing the customer
    curtime += elap;

    printf("%s from line %d checks out at time %d.\n",
        cust->name,cust->lineNumber,curtime);

    // release the customer record storage
    free(cust);
}

// testcase -- process a test case
void
testcase(FILE *fi)
{
    queue *q;
    customer *cust;

    // reset all queues
    // NOTE: probably not required
    for (int qidx = 0;  qidx < NUMLINES;  ++qidx) {
        q = &queue_list[qidx];
        qinit(q);
    }

    // get number of customers for this case
    int numCustomers;
    fscanf(fi," %d", &numCustomers);

    // read in all customer records for this test case
    for (int icust = 0;  icust < numCustomers;  ++icust) {
        cust = malloc(sizeof(*cust));

        fscanf(fi," %d", &cust->time);
        fscanf(fi," %d", &cust->lineNumber);
        fscanf(fi," %s", cust->name);
        fscanf(fi," %d", &cust->numberItems);

        // add customer to appropriate line/queue
        q = &queue_list[cust->lineNumber - 1];
        enqueue(q,cust);
    }

    // set current time to [way in the] past
    curtime = TIME_PAST;

    while (1) {
        // find the next customer
        cust = custfind();

        // no more customers
        if (cust == NULL)
            break;

        // service customer
        custdo(cust);
    }
}

int
main(int argc, char **argv)
{
    char *ifile;
    FILE *fi;

    --argc;
    ++argv;

    // open the input file
    if (argc > 0)
        ifile = *argv;
    else
        ifile = "input.txt";
    fi = fopen(ifile,"r");
    if (fi == NULL) {
        perror(ifile);
        exit(1);
    }

    // get number of test cases
    int testCases;
    fscanf(fi," %d", &testCases);

    // process all test cases
    for (;  testCases > 0;  --testCases)
        testcase(fi);

    fclose(fi);

    return 0;
}
</code>```

Body:
I need to enqueue a whole struct customer in the queue - I think. This is my homework. I am not asking for an answer. I need a mentor to explain what I am missing and what I have right per the assignment. I am very new. This is my second program. see below... thanks btw.

A store is having customers queue in several lines. After the cashier finishes helping a customer, he will survey all of the lines that are currently queued. Of all of the customers at the front of those lines, he’ll take the customer who has the fewest number of items. If there are two customers with the same number of items, he’ll take the customer who comes from the smaller line number. The lines are numbered 1 through 12. It’s possible that some of these lines will be empty, in which case these lines are ignored. The number of seconds the store clerk takes to check out a customer is 30 plus 5 times the number of items. Thus, if a customer has 8 times, the clerk would check her out in 30 + 8*5 = 70 seconds.
The Problem
You will write a program that reads in information about customers: which line they go to the back of (1 through 12), at what time (in seconds) they enter that line, and the number of items they have, and determines at what time each customer will check out.

Sample Input:

2

5
10 1 STEVEN 12
12 6 AHMAD 8
13 1 JENNY 40
22 6 JERMAINE 39
100000 12 AMALIA 53

6
100 1 A 100
200 2 B 99
300 3 C 98
400 4 D 97
500 5 E 96
600 6 F 95

Sample Output:

STEVEN from line 1 checks out at time 100.
AHMAD from line 6 checks out at time 170.
JERMAINE from line 6 checks out at time 395.
JENNY from line 1 checks out at time 625.
AMALIA from line 12 checks out at time 100295.

A from line 1 checks out at time 630.
F from line 6 checks out at time 1135.
E from line 5 checks out at time 1645.
D from line 4 checks out at time 2160.
C from line 3 checks out at time 2680.
B from line 2 checks out at time 3205.

Implementation Restrictions:

You must create a struct that stores information about a customer (name, number of items, line number, time entering line). Note that the storage of the line number is redundant, but is designed to ease implementation.

You must create a node struct for a linked list of customers. This struct should have a pointer to a customer struct, and a pointer to a node struct.

You must create a struct to store a queue of customers. This struct should have two pointers – one to the front of the queue and one to the back.

You must implement all of the lines that form as an array of size 12 (stored as a constant) of queues.

You must dynamically allocate memory as appropriate for linked lists.

Your queue must support the following operations:
a. Enqueue
b. Dequeue
c. Return the front of the queue WITHOUT dequeing d. Empty (returns 1 if the queue is empty, 0 if it is not)

You must free memory appropriately. Namely, when you dequeue, you’ll free memory for a node, but you will NOT free memory for the customer. You will free this memory a bit later right after you calculate when that customer will finish checking out.

Due to the nature of the problem, when you process the input, you can add everyone into their appropriate lines right at the beginning, before checking anyone out.

This wouldn’t work in all simulations (some of which you have to do in time order), but because there is ONLY one check out line, you can get away with it. The only thing you have to be cognizant about is that when you select a line, if the current time is, 100 for example, and three lines have customers who arrived before time 100 and the other lines have customers in the front who arrived AFTER time 100, you have to ignore the customers in those lines who arrived after time 100. In the case that all the lines have customers who arrived after time 100, you would take the line which has a customer who arrived first. You are guaranteed no ties for arrival time so this would be unique.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define TRUE 1
#define FALSE 0

typedef char customerName[9];

typedef struct node
{
    int data;
    struct node *next;
}node;

typedef struct queue
{
    int size;
    int front;
    int back;
    int *array;
    unsigned capacity;

}queue;

typedef struct customer
{
    customerName name;//1-9 upper case letters
    int lineNumber;
    int time;
    int numberItems;
} customer;

int isEmpty(queue *q);
void initialize(queue *q);

void initialize(queue *q)
{
    q->size = 0;
    q->front = -1;
    q->back = -1;
}

int isEmpty(queue *q){
    return (q->size == 0);//returns 1 if empty or 0 if false
}

int isFull(queue *q)
{  return (q->size == q->capacity);  }

void enqueue(queue *q, int item)
{
    if (isFull(q))
        return;
    q->back = (q->back + 1)%q->capacity;
    q->array[q->back] = item;
    q->size = q->size + 1;
}

int dequeue(queue *q)
{
    if (isEmpty(q))
        return 0;
    int item = q->array[q->front];
    q->front = (q->front + 1)%q->capacity;
    q->size = q->size - 1;
    return item;
}

int front(queue* q){
    if(isEmpty(q)){
        return 0;
    }
    return q->array[q->front];
}

int main(int argc, const char * argv[]) {

    int testCases = 0;
    scanf("%d", &testCases);

    if(testCases > 0 && testCases <= 25){//shortcircuiting???

    while (testCases--){

        queue *q;
        q = malloc(sizeof(queue));
        initialize(q);// starting new queue

        int numCustomers;
        scanf("%d", &numCustomers);

        if(numCustomers < 0 || numCustomers > 11){
            return 0;
        }

        struct customer newCustomer[1];

        for ( int i = 0; i < numCustomers; i++){
            scanf("%d", &newCustomer[i].time);
            scanf("%d", &newCustomer[i].lineNumber);
            scanf("%s", newCustomer[i].name);
            scanf("%d", &newCustomer[i].numberItems);
            enqueue(q, newCustomer[i].time);
            enqueue(q, newCustomer[i].lineNumber);

        }

        for ( int i = 0; i < numCustomers; i++){
            printf("%d %d %s %d\n", newCustomer[i].time, newCustomer[i].lineNumber, newCustomer[i].name, newCustomer[i].numberItems);

               }

    }
}
    return 0;
}

Here is my latest code:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define TRUE 1
#define FALSE 0
#define NUMLINES 12
int currtime = 0;

typedef char customerName[9];

typedef struct node
{
    int data;
    struct customer* data;
    struct node* next;

}node;

typedef struct queue
{
    node* front;
    node* back;
}queue;

typedef struct customer
{
    customerName name;//1-9 upper case letters
    int lineNumber;
    int time;
    int numberItems;
} customer;

typedef struct node *newNode;//define a node pointer

node createNode()
{
    newNode temp;//declare node
    temp = (newNode)malloc(sizeof(struct node));//allocate memory
    temp->next = NULL;//next point to null
    return *temp;// return the new node

}

struct queue* createQueue()
{
    struct queue* q = (struct queue*)malloc(sizeof(struct queue));
    q->front = q->back = NULL;
    return q;
}

int isEmpty(queue *q){
    return (q->back == NULL);//returns 1 if empty or 0 if false
}

void enqueue(queue *q, customer* data)
{
        // Create a new LL node
       struct node* temp = createNode(data);

       // If queue is empty, then new node is front and back both
       if (q->back == NULL) {
           q->front = q->back = temp;
           return;
       }

       // Add the new node at the end of queue and change back
       q->back->next = temp;
       q->back = temp;
}

void dequeue(queue *q)
{
     if (q->front == NULL)
           return;

       // Store previous front and move front one node ahead
       struct node* temp = q->front;
       q->front = q->front->next;

       // If front becomes NULL, then change rear also as NULL
       if (q->front == NULL)
           q->back = NULL;

       free(temp);
}

int front(queue* q){
    if(isEmpty(q)){
        return 0;
    }
    return q->front;
}

int main(int argc, const char * argv[]) {

    int testCases = 0;
    scanf("%d", &testCases);

    if(testCases > 0 && testCases <= 25){//shortcircuiting???

    while (testCases--){

        queue *q;
        q = malloc(sizeof(queue));
        initialize(q);// starting new queue

        int numCustomers;
        scanf("%d", &numCustomers);

        if(numCustomers < 0 || numCustomers > 11){
            return 0;
        }

        struct customer newCustomer[11];

        for ( int i = 0; i < numCustomers; i++){
            scanf("%d", &newCustomer[i].time);
            scanf("%d", &newCustomer[i].lineNumber);
            scanf("%s", newCustomer[i].name);
            scanf("%d", &newCustomer[i].numberItems);
            enqueue(q, newCustomer[i].time);
            enqueue(q, newCustomer[i].lineNumber);

        }

        for ( int i = 0; i < numCustomers; i++){
            printf("%d %d %s %d\n", newCustomer[i].time, newCustomer[i].lineNumber, newCustomer[i].name, newCustomer[i].numberItems);

               }

    }
}
    return 0;
}

int main(int argc, const char * argv[]) {

    int testCases = 0;
    scanf("%d", &testCases);

    if(testCases > 0 && testCases <= 25){//shortcircuiting???

    while (testCases--){

        queue *q;
        q = malloc(sizeof(queue));
        qinit(q);// starting new queue

        int numCustomers;
        scanf("%d", &numCustomers);

        if(numCustomers < 0 || numCustomers > 11){
            return 0;
        }

        queue* customerArray = (queue*) malloc(sizeof(queue) * 12);

        for ( int i = 0; i < numCustomers; i++){

            customer* newCustomer = (customer*) malloc(sizeof(customer));

            scanf("%d", &(newCustomer->time));
            scanf("%d", &(newCustomer->lineNumber));
            scanf("%s", newCustomer->name);
            scanf("%d", &(newCustomer->numberItems));
            enqueue(&customerArray[newCustomer->lineNumber - 1], newCustomer);
        }

        int totalTime = INT_MAX;

        for(int i=0;i<12;i++)
        {
        customer* frontCustomer = qfront(&customerArray[i]);
         if(totalTime < frontCustomer->time)
            {
                totalTime = frontCustomer->time;
            }
            free(frontCustomer);
         }

       while(numCustomers--) {

           int customerToCheckOutLine = 0; int minNumberOfItems = INT_MAX;

        for( int j=11 ; j>=0; j--){

            customer* frontCustomer = qfront(&customerArray[j]);
            if(frontCustomer->time <= totalTime)
            {
                if(frontCustomer->numberItems < minNumberOfItems)
                {
                    customerToCheckOutLine = frontCustomer->lineNumber;
                    minNumberOfItems = frontCustomer->numberItems;
                }
                free(frontCustomer);
            }
        }

        customer* customerToCheckOut = qfront(&customerArray[customerToCheckOutLine -1 ]);
        totalTime += 30;
        totalTime += (customerToCheckOut->numberItems) * 5;
           dequeue(&customerArray[customerToCheckOutLine - 1]);
       }
        free(customerArray);

    }
}
    return 0;
}

Body:
Your queue related functions look okay.

But, there are some bugs and the code needs refactoring to handle more things.

Your queue element array should be of type node * instead of int *.

You need the newCustomer array to be of length numCustomers (i.e. not 1).

At present, you have a single queue. But, you need an array of queues, one for each line, so an array length of 12.

When you queue a customer, you must select the queue [from the array of queues] based on the line number the customer is getting on.

Here's a biggie:

You can't queue two separate entries, one being time and the other being lineNumber. Well, you can I guess, but it's messy.

The way I'd do it is to change the data element of the node struct to be a pointer to the customer record. That way, every bit of data you need to determine the servicing order is [already] in the customer struct.

Anyway, here's some refactored code.

Per your request, it's not a solution, but some sample code as a basis for implementing the above fixes/suggestions.

You still have to change the queue struct and all queue related functions (if you decide to change the struct as I've suggested).

And, you still have to implement the selection/ordering process. And, the cleanup/deallocation.

This won't compile as is, because it's a "suggestion", but here it is:

 typedef char customerName[9];

typedef struct customer {
    customerName name;                  // 1-9 upper case letters
    int lineNumber;
    int time;
    int numberItems;
} customer;

typedef struct node {
#if 0
    int data;
#else
    customer *data;
#endif
    struct node *next;
} node;

typedef struct queue {
    int size;
    int front;
    int back;
#if 0
    int *array;
#else
    node *array;
#endif
    unsigned capacity;
} queue;

#if 1
#define NUMLINES        12
queue queue_list[NUMLINES];
#endif

int isEmpty(queue *q);
void initialize(queue * q);

void
initialize(queue *q)
{
    q->size = 0;
    q->front = -1;
    q->back = -1;
}

int
isEmpty(queue *q)
{
    return (q->size == 0);              // returns 1 if empty or 0 if false
}

int
isFull(queue *q)
{
    return (q->size == q->capacity);
}

void
enqueue(queue *q, int item)
{
    if (isFull(q))
        return;
    q->back = (q->back + 1) % q->capacity;
    q->array[q->back] = item;
    q->size = q->size + 1;
}

int
dequeue(queue *q)
{
    if (isEmpty(q))
        return 0;
    int item = q->array[q->front];

    q->front = (q->front + 1) % q->capacity;
    q->size = q->size - 1;
    return item;
}

int
front(queue *q)
{
    if (isEmpty(q)) {
        return 0;
    }
    return q->array[q->front];
}

int
main(int argc, const char *argv[])
{
    queue *q;

    int testCases = 0;

    scanf(" %d", &testCases);

    // NOTE/BUG: you need a separate queue for each line
    for (int qidx = 0;  qidx < NUMLINES;  ++qidx) {
        q = &queue_list[qidx];
        initialize(q);
    }

    // shortcircuiting???
    if (testCases > 0 && testCases <= 25) {
        while (testCases--) {
#if 0
            queue *q;
#endif

#if 0
            q = malloc(sizeof(queue));
            initialize(q);              // starting new queue
#endif

            int numCustomers;

            scanf(" %d", &numCustomers);

            if (numCustomers < 0 || numCustomers > 11) {
                return 0;
            }

            // NOTE/BUG: you need a larger array of customers
#if 0
            struct customer newCustomer[1];
#else
            struct customer newCustomer[numCustomers];
#endif

            for (int i = 0; i < numCustomers; i++) {
                customer *cust = &newCustomer[i];

                scanf(" %d", &cust->time);
                scanf(" %d", &cust->lineNumber);
                scanf(" %s", cust->name);
                scanf(" %d", &cust->numberItems);

                // NOTE/BUG: customer must be queued to the queue for the
                // line number they're on
                // NOTE/BUG: queue a single entry for each customer
#if 0
                enqueue(q, cust->time);
                enqueue(q, cust->lineNumber);
#else
                q = &queue_list[cust->lineNumber - 1];
                enqueue(q,cust);
#endif
            }

            for (int i = 0; i < numCustomers; i++) {
                printf("%d %d %s %d\n",
                    newCustomer[i].time,
                    newCustomer[i].lineNumber,
                    newCustomer[i].name,
                    newCustomer[i].numberItems);
            }
        }
    }

    return 0;
}

UPDATE:

woah, this is amaze balls. thank you so much. I think the assignment is confusing because he says the assignment is queues with linked list not an array but like you said it needs to be an array of queues. that would suggest multiple entries into a single line. so in a sense this is both an queues with linked lists and array?

You need an array of queues, indexed by linenumber. This is not to be confused with the q->array element within the queue, which is different.

I just completed a working and tested version [for myself, because I'm crazy that way :-)]. I had the same confusion.

The queue is a ring queue [with array]. If the array pointer is a customer *, I couldn't find a good way to use node. The only way to do it would be to convert queue into a linked list header struct. That would require queue to be restructured [along will all the access functions for it ;-)].

But, before doing that, if we keep the array/ring method, then initialize needs to take a capacity arg (called with initialize(q,numCustomer);). And, it needs to do (e.g.) q->array = realloc(q->array,sizeof(customer *) * capacity);

And, enqueue needs a fix: the increment of q->back needs to be moved after the q->array[q->back] = item;. Currently, there is an off by one gap.

To convert to a linked list:

The structs change a bit:

typedef struct node {
    customer *data;
    struct node *next;
} node;

typedef struct queue {
    node *front;
} queue;

You have an isFull function. That's not part of the requirements. If we switch queue into a linked list header for a list of node, it isn't even relevant/meaningful since, now, there is no maximum [as there was with q->capacity].

Now, when doing enqueue(q,cust);, the function would malloc a new node and append it to the end of the linked list. And, setup of (e.g.) newnode->next and newnode->data = cust;

When doing dequeue, it pops off the front element (a node), does cust = curnode->data;, then free(curnode), and returns cust.

Based on my rereading the requirements, I believe that this is what's required, and actually makes sense of all of them.

In other words, you can implement a queue with just a linked list (vs. what you did which was a ring queue with array--which I've also done in the past).

the ordering process is part of the reason I am so confused. I don't know where to do this. The list is already ordered by time the customer went to check out. I just need to calculate the total cashier time.there is only one cashier so all the people are served in order of entering the queue.

This is a bit tricky. You have to have a curtime global to keep track of the current time. Initially, this has to be set to the minimum of all cust->time values.

As you loop through all queues [i.e. waiting lines] to look at the first customer on the line, you have to do the following:

You skip the queue if it's empty.

You skip any customer if they have an arrival date in the future (i.e. cust->time > curtime).

Now you can "select" the customer. You need the find "best" customer [for the next one to be serviced]. That is, the one with the smallest order. The 2nd criteria of: with a tie, the customer with the lowest line number wins is handled automatically if you only update the "best" value if (cust->numberItems < best->numberItems) because we're traversing the queue_list array from low to high.

Then, service the "best" customer (i.e. print the message). Then, increment curtime by the elapsed time it takes to service the customer.

Repeat this until all queues are empty.

But, there is one gotcha. It happens with AMALIA.

The arrival time for this customer is so far in the future that the customer selection will fail to find any "best" customer because amalia->time is greater than curtime. Thus, it seems like AMALIA is not ready to be serviced.

So, if the selection fails (i.e. best is null), we have to loop through all front customers [again] and set curtime to the minimum of all their arrival times.

Then, we rescan/reselect for "best". Now, AMALIA will be selected

UPDATE #2:

in your example I don't understand what the #elseif etc. what are those? other than the obvious, I have never seen this

The lines starting with #if are preprocessor statements [just like #include, #ifdef, #else, #endif

The preprocessor is used to include/exclude code at compile time (vs using a real if language statement). You can think of the preprocessor as a separate pass before compilation that performs the conditional actions before passing the resultant file to the compile stage.

In my examples, I'm using them to show old code [yours] vs. new code [mine]:

#if 0
    // old code ...
    x = 1;
#else
    // new code ...
    x = 2;
#endif

When compiled, the old code is excluded, the new code is included as if we had done:

    // new code ...
    x = 2;

This is a useful technique in general. It allows you to "comment out" code that you suspect might be a bug. Or, for debug printf code. Or, you have working code (the "old" code), but you want to try something possibly cleaner or more efficient (the "new" code). You can flip back and forth during development just by changing #if 0 to #if 1 or vice versa

You can see the intermediate file by doing:

cc -E -P -o myfile.i myfile.c

Later on, when your code is [fully ;-)] debugged, you could hand edit out the #if cases you don't need/want.

can you do that same kind of example but for the linked list only implementation? or is that asking too much? :) why is there only a *front and no back of the list?

For a simple singly linked list, we only truly need a head/front pointer.

We don't need size because the empty case is: q->front == NULL. size is primarily useful if we had to sort the linked list (it saves a pass on the list to get the number of elements).

Using q->back adds a slight degree of complexity. It's a speedup when appending to the queue/list. If we don't have it, we find the last element in the list by traversing it. If we have back, that is the last element.

A singly linked list is sufficient for your use case. But, just for completeness, I've added doubly linked list support. We add a prev element to node [the backwards link].

Below, I've coded up the linked list structs and functions. To allow you to see the various modes, each optional element is wrapped in preprocessor #if/#endif pairs to include/exclude code, based on setting the given option on/off

DLINK [doubly linked list] is off by default

To enable it on a one time basis, you could do:

cc -DDLINK=1 -c myfile.c

Likewise for other options.

Anyway, here's the queue code based on a linked list:

// customer record
typedef char customerName[9];
typedef struct customer {
    customerName name;                  // 1-9 upper case letters
    int lineNumber;                     // line number customer gets on
    int time;                           // arrival time at line
    int numberItems;                    // number of items customer has
} customer;

// 1=use queue q->back
// need this for _doubly_ linked list
// speedup for append to end of queue for singly linked
#ifndef QBACK
#define QBACK       1
#endif

// 1=use queue q->size
#ifndef QSIZE
#define QSIZE       1
#endif

// 1=use doubly linked list
#ifndef DLINK
#define DLINK       0
#endif

// force QBACK on if doing doubly linked list
#if DLINK
#undef QBACK
#define QBACK       1
#endif

// [singly linked] queue element
typedef customer *qitem;
typedef struct node {
    qitem data;                         // pointer to actual data
    struct node *next;                  // forward pointer to next item
#if DLINK
    struct node *prev;                  // backward pointer to previous item
#endif
} node;

// queue definition (singly linked list)
// NOTE:
typedef struct queue {
    node *front;                        // pointer to first node in list
#if QBACK
    node *back;                         // pointer to last node in list
#endif
#if QSIZE
    int size;                           // current number of elements in list
#endif
} queue;

// list of queues (indexed by lineNumber - 1)
#define NUMLINES        12
queue queue_list[NUMLINES];

// qinit -- initialize/reset queue
void
qinit(queue *q)
{

    q->front = NULL;

#if QSIZE
    q->size = 0;
#endif

#if QBACK
    q->back = NULL;
#endif
}

// qempty -- returns 1 if empty or 0 if false
int
qempty(queue *q)
{
    // NOTE: size really isn't needed
#if 0
    return (q->size == 0);
#else
    return (q->front == NULL);
#endif
}

// enqueue -- append element to end of queue
void
enqueue(queue *q, qitem data)
{
    node *newnode;
    node *prev;

    newnode = malloc(sizeof(node));
    newnode->next = NULL;
    newnode->data = data;

    // NOTE: this is the only place where back is a speedup
#if QBACK
    prev = q->back;
#else
    // what we have to do find the back of the queue with only a front pointer
    prev = NULL;
    for (node *cur = q->front;  cur != NULL;  cur = cur->next)
        prev = cur;
#endif

    // append to tail of list
    if (prev != NULL)
        prev->next = newnode;

    // add to end of empty list
    else
        q->front = newnode;

#if DLINK
    newnode->prev = prev;
#endif

#if QBACK
    q->back = newnode;
#endif

#if QSIZE
    q->size += 1;
#endif
}

// dequeue -- dequeue from the front of the queue
qitem
dequeue(queue *q)
{
    node *curnode;
    qitem data;

    do {
        curnode = q->front;

        // bug out if list is empty
        if (curnode == NULL) {
            data = NULL;
            break;
        }

        // get node's data value (e.g. pointer to customer struct)
        data = curnode->data;

#if QBACK
        node *back = q->back;
#if DLINK
        curnode->prev = back;
#endif
        if (curnode == back)
            q->back = curnode->next;
#endif

        q->front = curnode->next;

#if QSIZE
        q->size -= 1;
#endif

        // release the node's storage back to the heap
        free(curnode);
    } while (0);

    return data;
}

// qfront -- peek at front of queue
qitem
qfront(queue *q)
{
    node *curnode;
    qitem data;

    curnode = q->front;
    if (curnode != NULL)
        data = curnode->data;
    else
        data = NULL;

    return data;
}

UPDATE #3:

so my main function has a memory leak and I cannot find it. I am trying to learn Valgrind and gdb but there is a learning curve. My Valgrind outran is like 90,000 characters for some reason and doesn't say hey I have a memory leak. I don't even know what line. I appended my new main to the bottom of the above code.

A few issues:

You malloc the q pointer at the top of the outer while (testCases--) loop but do not free it.

But, as I mentioned, you need an array of queues [which can be a fixed array] and you've already done that.

But, q was your original/legacy code. The rest of your code no longer uses q. You just forgot to remove it.

You are now using customerArray instead. But, you are not calling qinit on each array element, so you could have a random data in each.

In the problem definition, the number of customer lines is fixed at 12, so you really don't need to malloc and free it. That's why I used a global array instead.

You have a bug in your totalTime calculation loop. You're doing a free of the customer record. So, the record is no longer valid in the loop below it.

And, in that second loop, you're doing a second free of the same struct. So, at present, this is a "double free" bug. The second loop is actually the correct place for the free [not the first loop]

This program is ambitious for a second ever assignment, so you're "being thrown out into the middle of the lake and being asked to swim to shore".

I would have expected a few more intermediate steps/programs before trying to code up this one.

When starting out, as you are, sometimes it's as important to study working code as it is to write it from scratch.

So, spoiler alert, here's my final, fully working code:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define TIME_PAST       -1              // infinite time in the past
#define TIME_FUTURE     INT_MAX         // infinite time in the future
int curtime;                            // current time

// customer record
typedef char customerName[9];
typedef struct customer {
    customerName name;                  // 1-9 upper case letters
    int lineNumber;                     // line number customer gets on
    int time;                           // arrival time at line
    int numberItems;                    // number of items customer has
} customer;

// 1=use queue q->back
// need this for _doubly_ linked list
// speedup for append to end of queue for singly linked
#ifndef QBACK
#define QBACK       1
#endif

// 1=use queue q->size
#ifndef QSIZE
#define QSIZE       1
#endif

// 1=use doubly linked list
#ifndef DLINK
#define DLINK       0
#endif

// force QBACK on if doing doubly linked list
#if DLINK
#undef QBACK
#define QBACK       1
#endif

// [singly linked] queue element
typedef customer *qitem;
typedef struct node {
    qitem data;                         // pointer to actual data
    struct node *next;                  // forward pointer to next item
#if DLINK
    struct node *prev;                  // backward pointer to previous item
#endif
} node;

// queue definition (singly linked list)
// NOTE:
typedef struct queue {
    node *front;                        // pointer to first node in list
#if QBACK
    node *back;                         // pointer to last node in list
#endif
#if QSIZE
    int size;                           // current number of elements in list
#endif
} queue;

// list of queues (indexed by lineNumber - 1)
#define NUMLINES        12
queue queue_list[NUMLINES];

// qinit -- initialize/reset queue
void
qinit(queue *q)
{

    q->front = NULL;

#if QSIZE
    q->size = 0;
#endif

#if QBACK
    q->back = NULL;
#endif
}

// qempty -- returns 1 if empty or 0 if false
int
qempty(queue *q)
{
    // NOTE: size really isn't needed
#if 0
    return (q->size == 0);
#else
    return (q->front == NULL);
#endif
}

// enqueue -- append element to end of queue
void
enqueue(queue *q, qitem data)
{
    node *newnode;
    node *prev;

    newnode = malloc(sizeof(node));
    newnode->next = NULL;
    newnode->data = data;

    // NOTE: this is the only place where back is a speedup
#if QBACK
    prev = q->back;
#else
    // what we have to do find the back of the queue with only a front pointer
    prev = NULL;
    for (node *cur = q->front;  cur != NULL;  cur = cur->next)
        prev = cur;
#endif

    if (prev != NULL)
        prev->next = newnode;
    else
        q->front = newnode;

#if DLINK
    newnode->prev = prev;
#endif

#if QBACK
    q->back = newnode;
#endif

#if QSIZE
    q->size += 1;
#endif
}

// dequeue -- dequeue from the front of the queue
qitem
dequeue(queue *q)
{
    node *curnode;
    node *nextnode;
    qitem data;

    do {
        // get the first node
        curnode = q->front;

        // if none, return null data
        if (curnode == NULL) {
            data = NULL;
            break;
        }

        // get the data payload
        data = curnode->data;

        // point to the next node (i.e. second node)
        nextnode = curnode->next;

#if QBACK
        node *back = q->back;
#if DLINK
        curnode->prev = back;
#endif
        if (curnode == back)
            q->back = nextnode;
#endif

        q->front = nextnode;

#if QSIZE
        q->size -= 1;
#endif

        free(curnode);
    } while (0);

    return data;
}

// qfront -- peek at front of queue
qitem
qfront(queue *q)
{
    node *curnode;
    qitem data;

    curnode = q->front;
    if (curnode != NULL)
        data = curnode->data;
    else
        data = NULL;

    return data;
}

// custfind -- find next customer to serve
customer *
custfind(void)
{
    int pass;
    int qidx;
    queue *q;
    int mintime;
    int moreflg;
    customer *cust;
    customer *best;

    // pass 1:
    // - remember the minimum time
    // - find best using curtime
    for (pass = 1;  pass <= 2;  ++pass) {
        best = NULL;
        mintime = TIME_FUTURE;
        moreflg = 0;

        // scan all queues -- examine _first_ customer on each line
        for (qidx = 0;  qidx < NUMLINES;  ++qidx) {
            q = &queue_list[qidx];

            // get first customer on current line
            cust = qfront(q);
            if (cust == NULL)
                continue;

            // remember that there is at least _one_ customer waiting
            moreflg = 1;

            // remember the minimum time
            if (cust->time < mintime)
                mintime = cust->time;

            // has the customer actually arrived yet? -- skip if not
            if (cust->time > curtime)
                continue;

            // no previous "best" customer -- set from current
            if (best == NULL) {
                best = cust;
                continue;
            }

            // get better customer (has fewer items to check out)
            if (cust->numberItems < best->numberItems) {
                best = cust;
                continue;
            }
        }

        // no more customers
        if (! moreflg)
            break;

        // found a best match
        // dequeue and free node
        if (best != NULL) {
            q = &queue_list[best->lineNumber - 1];
            dequeue(q);
            break;
        }

        // no best match found
        // all customers are in the future [based on curtime]
        // set new current time based on minimum time of all remaining customers
        // the second pass _will_ find at least one after we do this
        curtime = mintime;
    }

    return best;
}

// custdo -- check out customer
void
custdo(customer *cust)
{
    int elap;

    // current time has to be _at least_ the arrival time
    if (curtime < cust->time)
        curtime = cust->time;

    // get amount of time it takes to service this customer
    elap = 0;
    elap += 30;
    elap += cust->numberItems * 5;

    // set current time after servicing the customer
    curtime += elap;

    printf("%s from line %d checks out at time %d.\n",
        cust->name,cust->lineNumber,curtime);

    // release the customer record storage
    free(cust);
}

// testcase -- process a test case
void
testcase(FILE *fi)
{
    queue *q;
    customer *cust;

    // reset all queues
    // NOTE: probably not required
    for (int qidx = 0;  qidx < NUMLINES;  ++qidx) {
        q = &queue_list[qidx];
        qinit(q);
    }

    // get number of customers for this case
    int numCustomers;
    fscanf(fi," %d", &numCustomers);

    // read in all customer records for this test case
    for (int icust = 0;  icust < numCustomers;  ++icust) {
        cust = malloc(sizeof(*cust));

        fscanf(fi," %d", &cust->time);
        fscanf(fi," %d", &cust->lineNumber);
        fscanf(fi," %s", cust->name);
        fscanf(fi," %d", &cust->numberItems);

        // add customer to appropriate line/queue
        q = &queue_list[cust->lineNumber - 1];
        enqueue(q,cust);
    }

    // set current time to [way in the] past
    curtime = TIME_PAST;

    while (1) {
        // find the next customer
        cust = custfind();

        // no more customers
        if (cust == NULL)
            break;

        // service customer
        custdo(cust);
    }
}

int
main(int argc, char **argv)
{
    char *ifile;
    FILE *fi;

    --argc;
    ++argv;

    // open the input file
    if (argc > 0)
        ifile = *argv;
    else
        ifile = "input.txt";
    fi = fopen(ifile,"r");
    if (fi == NULL) {
        perror(ifile);
        exit(1);
    }

    // get number of test cases
    int testCases;
    fscanf(fi," %d", &testCases);

    // process all test cases
    for (;  testCases > 0;  --testCases)
        testcase(fi);

    fclose(fi);

    return 0;
}


来源: stackexchange

问:
Copy Texture2D to leave original unchanged
How to I properly copy a Texture2D in Unity, I've tried using Graphics.CopyTexture(texture, copy); to have it tell me that the two images are incompatible, how do I work around this and get a perfect copy of the image, Everything I've looked up either relates to how to crop the copied image or when using RenderTextures but I can't find any information about how to create a copy Texture2D that is identical, in size and pixel colors.

答:
Try using the constructor of the Texture2D class, and the methods SetPixels and Apply.

```<code>Texture2D copyTexture = new Texture2D(originalTexture.width, originalTexture.height);
copyTexture.SetPixels(originalTexture.GetPixels());
copyTexture.Apply();
</code>```

You may encounter an error:

```<code>UnityException: Texture 'YourTexture' is not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.
</code>```

And as it says. You solve it by clicking your texture in the project tab to open the Import Settings in the Inspector and check the Read/Write Enabled checkbox.

ContentLicense: CC BY-SA 4.0

Body:
Try using the constructor of the Texture2D class, and the methods SetPixels and Apply.

Texture2D copyTexture = new Texture2D(originalTexture.width, originalTexture.height);
copyTexture.SetPixels(originalTexture.GetPixels());
copyTexture.Apply();

You may encounter an error:

UnityException: Texture 'YourTexture' is not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.

And as it says. You solve it by clicking your texture in the project tab to open the Import Settings in the Inspector and check the Read/Write Enabled checkbox.


问:
Aspnet LinqtoTwitter - PageCycle Issues
I am currently working on the linqtotwitter library.

I am using cookies to store the token and key. My problem isnt with the api as much. It is more with ASP net and page life cycle.

The problem i have with my webform app is the same with the aspnet webform defaultasp sample same at linqtotwitter site.

This is how the api works

You pass the Credentials to Authorize object to Twitter context in a nut shell.

In the sample you authorize and etc. Once the page load the auth.screenname label is changed to your twitter handle because you authenicated and it passed the auth.credentials to the twittercontext.

This is where my problem is.  If I hit refresh the label is cleared out but I am still authenicated with twitter so I can post except i can not get values from the auth objects.

How would I keep the state on a refresh so I keep something like the auth.screenname or something else in memory.

I think i would need to preload the twitter authorized context but I have no idea about doing that.

I do not think using a hidden form element is proper because your masking the underlying problem.

If you want to see what  linqtotwitter is, it is  at http://linqtotwitter.codeplex.com/

答: You could throw the tokens into Session if you have it enabled, that might solve your issue.

ContentLicense: CC BY-SA 3.0

Title: Aspnet LinqtoTwitter - PageCycle Issues


问:
Convert elements of a list into binary
Suppose I have a list:

```<code>lst = [0, 1, 0, 0]
</code>```

How can I make python interpret this list as a binary number 0100 so that 2*(0100)  gives me 01000?

The only way that I can think of is to first make a function that converts the "binary" elements to corresponding integers(to base 10) and then use bin() function..

Is there a better way?

答:
slightly different approach with comprehension (i hope it will be helpful for someone)

```<code>arr =[192, 168, 0, 1]
arr_s = [bin(i)[2:].zfill(8) for i in ar]
num = int(''.join(arr_s), 2)
</code>```

same, but reverse order  (and also one-liner suitable for lambdas )

```<code>arr = [24, 85, 0]
num = int(''.join( [bin(i)[2:].zfill(8) for i in arr[::-1]] ), 2)
</code>```

using bit-wise and reduce:

```<code>reduce ((lambda x,y: (x<<8)|y), arr[::-1])
</code>```

Title: Convert elements of a list into binary

Body:
Suppose I have a list:

lst = [0, 1, 0, 0]

How can I make python interpret this list as a binary number 0100 so that 2*(0100)  gives me 01000?

The only way that I can think of is to first make a function that converts the "binary" elements to corresponding integers(to base 10) and then use bin() function..

Is there a better way?

Body:
slightly different approach with comprehension (i hope it will be helpful for someone)

arr =[192, 168, 0, 1]
arr_s = [bin(i)[2:].zfill(8) for i in ar]
num = int(''.join(arr_s), 2)

same, but reverse order  (and also one-liner suitable for lambdas )

arr = [24, 85, 0]
num = int(''.join( [bin(i)[2:].zfill(8) for i in arr[::-1]] ), 2)

using bit-wise and reduce:

reduce ((lambda x,y: (x<<8)|y), arr[::-1])


问:
Error when trying to grab invites of the guilds my bot is in
It somehow only works when I make a new channel, this does get irritating though considering people who will add my bot to their server won't make a new channel specifically for it.

Error:

```<code>{ DiscordAPIError: Unknown Channel
    at RequestHandler.execute (C:\Users\Multiverse\node_modules\discord.js\src\rest\RequestHandler.js:170:25)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  name: 'DiscordAPIError',
  message: 'Unknown Channel',
  method: 'post',
  path: '/channels/702061566601986049/invites',
  code: 10003,
  httpStatus: 404 }
</code>```

Code I'm using:

```<code>client.on("message", msg => {
  if (msg.content === "!guildinv") {
client.guilds.cache.forEach(guild => {
  guild.channels.cache.first().createInvite()
    .then(inv => console.log(`${guild.name} | ${inv.url}`)).catch(console.error);
</code>```

答:
This is probably because the first channel is a Category.

const textChannel = guild.channels.cache.find(c => c.type === "text");
if(textChannel) textChannel.createInvite()
//if there is no textChannel found it could mean there is no *cached* text channel
//so you should prob make a fallback to fetch for a text channel
//then again I think all channels are cached so I'm not sure
```

Also an alternative is  guild.fetchInvites();

https://discord.js.org/#/docs/main/stable/class/Guild?scrollTo=fetchInvites

Body:
It somehow only works when I make a new channel, this does get irritating though considering people who will add my bot to their server won't make a new channel specifically for it.

Error:

{ DiscordAPIError: Unknown Channel
    at RequestHandler.execute (C:\Users\Multiverse\node_modules\discord.js\src\rest\RequestHandler.js:170:25)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  name: 'DiscordAPIError',
  message: 'Unknown Channel',
  method: 'post',
  path: '/channels/702061566601986049/invites',
  code: 10003,
  httpStatus: 404 }

Code I'm using:

client.on("message", msg => {
  if (msg.content === "!guildinv") {
client.guilds.cache.forEach(guild => {
  guild.channels.cache.first().createInvite()
    .then(inv => console.log(`${guild.name} | ${inv.url}`)).catch(console.error);

Body:
This is probably because the first channel is a Category.

const textChannel = guild.channels.cache.find(c => c.type === "text");
if(textChannel) textChannel.createInvite()
//if there is no textChannel found it could mean there is no *cached* text channel
//so you should prob make a fallback to fetch for a text channel
//then again I think all channels are cached so I'm not sure

Also an alternative is  guild.fetchInvites();

https://discord.js.org/#/docs/main/stable/class/Guild?scrollTo=fetchInvites


答:
```<code>import numpy as np

# Create example arrays
arr1 = np.random.randint(10,size=(5, 4))
arr2 = np.random.randint(10,size=(5, 4))
arr3 = np.random.randint(10,size=(5, 4))
arr4 = np.random.randint(10,size=(5, 4))

# Combine all the arrays to match the dimensions mentioned in the question
arr_comb = np.array([[arr1, arr2],[arr3, arr4]])
print("Old array:")
print(arr_comb)

new_column_length = np.shape(arr_comb)[0] * np.shape(arr_comb)[1] * np.shape(arr_comb)[2]
# Reshape the array into a new array. The columns of the new array are what you requested
new_comb_arr = arr_comb.reshape(new_column_length,-1)

# e.g
print("First column of new array")
new_comb_arr[:,0]
</code>```

Which results in:

```<code>Old array:
[[[[2 7 0 0]
   [0 1 7 3]
   [5 7 4 2]
   [4 5 3 6]
   [4 8 2 0]]

  [[4 6 3 4]
   [6 5 3 7]
   [6 2 7 4]
   [9 1 8 2]
   [3 9 2 2]]]

 [[[6 8 3 4]
   [0 6 6 6]
   [1 8 1 2]
   [4 2 6 4]
   [7 8 0 2]]

  [[2 6 4 1]
   [4 7 1 4]
   [8 0 5 6]
   [4 7 4 7]
   [8 9 4 5]]]]
First column of new array
array([2, 0, 5, 4, 4, 4, 6, 6, 9, 3, 6, 0, 1, 4, 7, 2, 4, 8, 4, 8])
</code>```

Title: Creating new array from array indexing

Body:
Suppose I have the following array:

print(my_array)
(array([[[[5,  7,  3,  1],
          [-6, 0, -8, -2],
          [ 9 -7, -5, -9],
          [-1,  6,  0,  1],
          [-7, -8 , -3, 4]]],

        [[[-1,  5, -2, 2],
          [4,  -3, -1, 2],
          [-9,  0,  7, 1],
          [-4,  6, -5, -8],
          [-7, -3,  0 , 1]]]]),

 array([[[[ 7, 9 , 4, -3 ],
          [-4, 7, -1, -9],
          [6,  0, -3,  -7],
          [ 1,  6,  9, -3],
          [-4, -1, -9 , -6]]],

        [[[ 0, 8,  2, 6],
          [4,  5,  1,  2],
          [3,  7,  5, 2],
          [6, -1,  9,  5],
          [ 0,  5, 7,  7]]]]))

Then I want to form four new arrays, where the first new array is created from first columns of all nested arrays in my_array, the second from second columns etc.. such that

A = array([5,-6,9,-1,-7,-1,4,-9,-4,-7,7,-4,6,1,-4,0,4,3,6,0])

And the second array formed by second columns of each nested, like so:

B = array([7,0,-7,6,-8,5,-3,0,6,-3,9,7,0,6,-1,8,5,7,-1,5])

How can I do this?

Body:
import numpy as np

# Create example arrays
arr1 = np.random.randint(10,size=(5, 4))
arr2 = np.random.randint(10,size=(5, 4))
arr3 = np.random.randint(10,size=(5, 4))
arr4 = np.random.randint(10,size=(5, 4))

# Combine all the arrays to match the dimensions mentioned in the question
arr_comb = np.array([[arr1, arr2],[arr3, arr4]])
print("Old array:")
print(arr_comb)

new_column_length = np.shape(arr_comb)[0] * np.shape(arr_comb)[1] * np.shape(arr_comb)[2]
# Reshape the array into a new array. The columns of the new array are what you requested
new_comb_arr = arr_comb.reshape(new_column_length,-1)

# e.g
print("First column of new array")
new_comb_arr[:,0]

Which results in:

Old array:
[[[[2 7 0 0]
   [0 1 7 3]
   [5 7 4 2]
   [4 5 3 6]
   [4 8 2 0]]

  [[4 6 3 4]
   [6 5 3 7]
   [6 2 7 4]
   [9 1 8 2]
   [3 9 2 2]]]

 [[[6 8 3 4]
   [0 6 6 6]
   [1 8 1 2]
   [4 2 6 4]
   [7 8 0 2]]

  [[2 6 4 1]
   [4 7 1 4]
   [8 0 5 6]
   [4 7 4 7]
   [8 9 4 5]]]]
First column of new array
array([2, 0, 5, 4, 4, 4, 6, 6, 9, 3, 6, 0, 1, 4, 7, 2, 4, 8, 4, 8])


问:
Vue - pass reactive prop from parent to child?
I know this has been asked a lot here in different forms, but I'm having trouble getting a child to be reactive to changes made in the parent. I have tried key changing, but that doesn't seem to work in this case.

Shouldn't a child component know to re-render itself when a prop it is receiving has changed?

For example (this is not my exact component, just an example of the data flow):

```<code><template>
  <div id="parent">
    <h1>Sort By</h1>
    <button @click"handleClick('alpha')">Alphabetical</button>
    <button @click"handleClick('price')">Price</button>
    <ChildComponent :sortBy="sortBy" :key="keyChangingDoesntWork" /> // doesn't update when 'sortBy' changes.
  </div>
</template>
<script>
// ...
name: "parent",
data(){
  return{
    sortBy: 'alpha',
  }
},
methods: {
  handleClick(by){
    if (by === 'alpha') {
      this.sortBy = 'alpha'
    } else {
      this.sortBy = 'price'
    }
  }
}
</script>
</code>```

// child

```<code><script>
  props: {
    sortBy: String
  }
  updated() {
    console.log(this.sortBy); // need this to change when buttons are clicked in parent
  }
</script>
</code>```

答:
You can watch props as below

Parent:

    <template>

Sort By

        <button @click="handleClick('alpha')">Alphabetical</button>
        <button @click="handleClick('price')">Price</button>

        <ChildComponent v-bind:sortBy="sortBy" />

    </template>

```
<p>Child:</p>
<pre class="lang-html prettyprint-override"><code>    <template>
    <div>
        <h5>Child: {{ sortBy }}</h5>
    </div>
    <!--  prop change watch-->
    </template>
    <script>
    export default {
      props: {
        sortBy: String,
      },
      watch: {
        sortBy: function (newVal, oldVal) {
          // watch it
          console.log("Prop changed: ", newVal, " | was: ", oldVal);
        },
      },
    };
    </script>
</code>```

Body:
I know this has been asked a lot here in different forms, but I'm having trouble getting a child to be reactive to changes made in the parent. I have tried key changing, but that doesn't seem to work in this case.

Shouldn't a child component know to re-render itself when a prop it is receiving has changed?

For example (this is not my exact component, just an example of the data flow):

<template>

Sort By

    <button @click"handleClick('alpha')">Alphabetical</button>
    <button @click"handleClick('price')">Price</button>
    <ChildComponent :sortBy="sortBy" :key="keyChangingDoesntWork" /> // doesn't update when 'sortBy' changes.

</template>

// child

Body:
You can watch props as below

Parent:

    <template>
    <div id="parent">
        <h1>Sort By</h1>
        <button @click="handleClick('alpha')">Alphabetical</button>
        <button @click="handleClick('price')">Price</button>

        <ChildComponent v-bind:sortBy="sortBy" />
    </div>
    </template>
    <script>
    import ChildComponent from './ChildComponent';
    export default {
        name: "parent",
        data() {
            return {
                sortBy: 'alpha',
                keyChangingDoesntWork: 1
            }
        },
        components: {
            'ChildComponent': ChildComponent
        },
        methods: {
            handleClick(by) {
                if (by === 'alpha') {
                    this.sortBy = 'alpha'
                } else {
                    this.sortBy = 'price'
                }
                return this.sortBy;
            }
        },
    }
    </script>

Child:

    <template>
    <div>
        <h5>Child: {{ sortBy }}</h5>
    </div>
    <!--  prop change watch-->
    </template>
    <script>
    export default {
      props: {
        sortBy: String,
      },
      watch: {
        sortBy: function (newVal, oldVal) {
          // watch it
          console.log("Prop changed: ", newVal, " | was: ", oldVal);
        },
      },
    };
    </script>


问:
Spark AR Studio how to move object after 3 seconds patch editor
I’ve successfully used a target tracker in Spark AR Studio with a simple plane object as a child of the target tracker to view in AR. When I view the target tracker with my phone, the plane is visible.

Simple enough, but I’m having trouble using the patch editor to move that plane after a specified amount of time, say 3 seconds. I’ve looked through documentation and couldn’t really find anything related to my issue. It’d be much appreciated if someone could help me figure out how to move this plane object after 3 seconds to a different location on my target tracker.

答: There are different ways it can be done. One way would be use the Runtime patch to get the current time, and a Greater Than patch to trigger an animation when the time passes 3 seconds.


问:
Notepad++ regex - how to remove the proxies from this list?
I have this list of user:pass:proxy

```<code>username1:password:124.144.86.130:3128
username2:password:124.144.86.238:3128
username3:password:124.144.86.180:3128
username4:password:128.20.185.250:3128
username5:password:124.144.164.40:3128
</code>```

how to get rid of proxy and keep Username:password using regex?

I want only

```<code>username1:password
username2:password
username3:password
username4:password
username5:password
</code>```

I've tried for ^[^:\r\n]*:[^:\r\n]*: but it remove user:pass and keep the proxy..

答:
Try this:

```<code>^\w.*?\:\w+
</code>```

Here is an example match: https://regex101.com/r/SzcwGa/1

or, you can use Substitution to remove what you do not need: https://regex101.com/r/SzcwGa/2

Find: (^\w.*?\:\w+)(.*)

Replace: $1

Body:
I have this list of user:pass:proxy

username1:password:124.144.86.130:3128
username2:password:124.144.86.238:3128
username3:password:124.144.86.180:3128
username4:password:128.20.185.250:3128
username5:password:124.144.164.40:3128

how to get rid of proxy and keep Username:password using regex?

I want only

username1:password
username2:password
username3:password
username4:password
username5:password

I've tried for ^[^:\r\n]*:[^:\r\n]*: but it remove user:pass and keep the proxy..

Body:
Try this:

^\w.*?\:\w+

Here is an example match: https://regex101.com/r/SzcwGa/1

or, you can use Substitution to remove what you do not need: https://regex101.com/r/SzcwGa/2

Find: (^\w.*?\:\w+)(.*)

Replace: $1


问:
Get comma separated string from Mysql
I'm saving a string from PHP to MySQL like this..

```<code>$groupid = "13, 14, 15, 16"
$write = mysql_query("INSERT INTO table VALUES ('','$groupid')");
</code>```

I'm then trying to extract data from the table if $a = "15"

```<code>$extract = mysql_query("SELECT * FROM table WHERE ustaffid='$ustaffid' AND groupid='$a'");
</code>```

How can I easily match what's in $groupid to $a, while extracting it? Can I do that with MySQL?

答:
You can use the find_in_set function here.</p>

```<code>SELECT *
    FROM table
    WHERE ustaffid='$ustaffid'
        AND FIND_IN_SET('$a', groupid) > 0
</code>```

Title: Get comma separated string from Mysql

Body:
I'm saving a string from PHP to MySQL like this..

$groupid = "13, 14, 15, 16"
$write = mysql_query("INSERT INTO table VALUES ('','$groupid')");

I'm then trying to extract data from the table if $a = "15"

$extract = mysql_query("SELECT * FROM table WHERE ustaffid='$ustaffid' AND groupid='$a'");

How can I easily match what's in $groupid to $a, while extracting it? Can I do that with MySQL?

Body:
You can use the find_in_set function here.

SELECT *
    FROM table
    WHERE ustaffid='$ustaffid'
        AND FIND_IN_SET('$a', groupid) > 0


问:
How to make top flex box row not push down bottom flex box row on hover
I have read through the similar issues, but have not been able to see an example that works. Using absolute will make all of the images stack on top of one another. My goal is that when an image in the top row increases in size on hover, it does not push down the images on the bottom row. Thank you!

This is the code:

import React, {Component} from 'react';
import { NavButton } from '../../atoms/NavButton/NavButton';
import './homepage.css';

export default class Homepage extends Component{

  render () {

    const { history } = this.props;

    return (

          <NavButton
            icon="timeline"
            history={history}
          />
          <NavButton
            icon="me"
            history={history}
          />
          <NavButton
            icon="learn"
            history={history}
          />

          <NavButton
            icon="meta"
            history={history}
          />
          <NavButton
            icon="projects"
            history={history}
          />
          <NavButton
            icon="education"
            history={history}
          />

    );
  }
}```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.homepage-outer-flexbox {
    display: flex;
    flex-direction: column;
}

.homepage-row-one {
    display: flex;
    flex-direction: row;
    flex: 1;
}

.homepage-row-two {
    display: flex;
    flex-direction: row;
    flex: 1;
}

.container {
    text-align: center;
    vertical-align: middle;
    margin-bottom: 20%;
}

.container > img {
    max-width: 65%;
    max-height: 65%;
}

.container > img:hover {
    max-width: 70%;
    max-height: 70%;
}</code>```

答:
You can try this.

```<code>.container > img:hover {
    transform: scale(1.1); /* Or something*/
}
</code>```

Example:

.img-container {
  display: flex;
  align-items: center;
}

.img-container>img {
  min-width: 0;
  width: 100%;
  transition: .4s ease;
}

.img-container>img:hover {
  transform: scale(1.1);
  /* Or something*/
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="img-container">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
</div></code>```

Body:
I have read through the similar issues, but have not been able to see an example that works. Using absolute will make all of the images stack on top of one another. My goal is that when an image in the top row increases in size on hover, it does not push down the images on the bottom row. Thank you!

This is the code:

import React, {Component} from 'react';
import { NavButton } from '../../atoms/NavButton/NavButton';
import './homepage.css';

export default class Homepage extends Component{

  render () {

    const { history } = this.props;

    return (

          <NavButton
            icon="timeline"
            history={history}
          />
          <NavButton
            icon="me"
            history={history}
          />
          <NavButton
            icon="learn"
            history={history}
          />

          <NavButton
            icon="meta"
            history={history}
          />
          <NavButton
            icon="projects"
            history={history}
          />
          <NavButton
            icon="education"
            history={history}
          />

    );
  }
}

.homepage-outer-flexbox {
    display: flex;
    flex-direction: column;
}

.homepage-row-one {
    display: flex;
    flex-direction: row;
    flex: 1;
}

.homepage-row-two {
    display: flex;
    flex-direction: row;
    flex: 1;
}

.container {
    text-align: center;
    vertical-align: middle;
    margin-bottom: 20%;
}

.container > img {
    max-width: 65%;
    max-height: 65%;
}

.container > img:hover {
    max-width: 70%;
    max-height: 70%;
}

Body:
You can try this.

.container > img:hover {
    transform: scale(1.1); /* Or something*/
}

Example:

.img-container {
  display: flex;
  align-items: center;
}

.img-container>img {
  min-width: 0;
  width: 100%;
  transition: .4s ease;
}

.img-container>img:hover {
  transform: scale(1.1);
  /* Or something*/
}

<div class="img-container">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
  <img src="https://image.freepik.com/free-photo/image-human-brain_99433-298.jpg">
</div>


问:
How to compile pmars-0.9.2 on Ubuntu 18.04? error: Makefile:116: recipe for target 'all' failed
I'm trying to compile a pmars-0.9.2 game, but stumbled on an error while passing the test, after command make -j4:

make[2]: *** [extractor/CMakeFiles/extractor.dir/backoff_sampler.cc.o] Error 1
 CMakeFiles/Makefile2:2561: recipe for target 'extractor/CMakeFiles/extractor.dir/all' failed
 make[1]: *** [extractor/CMakeFiles/extractor.dir/all] Error 2
 Makefile:116: recipe for target 'all' failed
 make: *** [all] Error 2

Can you tell me which installation drivers are missing to successfully complete the compilation?

答:
To view logs from an unpacked archived use command:

nano /home/user/Desktop/pmars-0.9.2/cdec/BUILDING

To build cdec, you'll need:

boost headers & boost program_options (you may need to install a package
like libboost-dev)

Instructions for building

1) Create a build directory and generate Makefiles using CMake

```<code>    mkdir my_build
    cd my_build
    cmake ..

If the cmake command completes successfully, you can proceed. If you have
libraries (such as Boost) installed in nonstandard locations, you may need
to run cmake with special options like -DBOOST_ROOT=/path/to/boost.
</code>```

2) Build

```<code>    make -j 2
</code>```

3) Test
        make test
        ./tests/run-system-tests.pl

Body:
To view logs from an unpacked archived use command:

nano /home/user/Desktop/pmars-0.9.2/cdec/BUILDING

To build cdec, you'll need:

boost headers & boost program_options (you may need to install a package
like libboost-dev)

Instructions for building

1) Create a build directory and generate Makefiles using CMake

    mkdir my_build
    cd my_build
    cmake ..

If the cmake command completes successfully, you can proceed. If you have
libraries (such as Boost) installed in nonstandard locations, you may need
to run cmake with special options like -DBOOST_ROOT=/path/to/boost.

2) Build

    make -j 2

3) Test
        make test
        ./tests/run-system-tests.pl