问:
wav file over UDP not playing back properly in unix with Alsa-lib
I'm trying to send a .wav file via UDP sockets from the server to the client and playing it back from the client side.

The file is 48kHz and 16 bits and has duration of 25 sec.

Since the server.c  is a small code section inside a larger C-RAN code module I'm checking it by passing a wav file from the stdin:

```<code>./SERVER < filename.wav
</code>```

and then as soon as I execute the client.c, the server starts sending the datagrams and the client.c starts playing them back. Everything is fine bu the audio is played back at a much faster speed, its like playing it back at twice the correct speed. Sometimes it starts playing back correctlyI but after a few seconds it speeds up.

I've  passed a large .txt file instead of the .wav file and the client recieves all the .txt file, from start to end.

Is there anything that I'm missing that I should take into account in order to playback the audio wav file correctly?

client.c code:

```<code>// Remote Radio Head - client side
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <alsa/asoundlib.h>
#include <dirent.h>

/* CONSTANTS */
#define PORT     8080
#define MAXLINE  1024
#define PAYLOAD_SIZE 128

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
/*************************************************
*          DRIVER CODE           *
*************************************************/
int main(int argc, char *argv[]) {
    // Sockets variables
    int sockfd;
    char buffer1[MAXLINE];
    char *data = "Hello from client, waiting for audio to playback";
    struct sockaddr_in     servaddr;

    // ALSA playback variables
    long loops;
    int rc;
    int size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;
    char *buffer2;
    /*********************************************
    *           ALSA DRIVERS SETUP               *
    *********************************************/
    // Open PCM device for playback.
    rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0) {
        fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
        exit(1);
    }
    // Allocate a hardware parameters object.
    snd_pcm_hw_params_alloca(&params);
    // Fill it in with default values.
    snd_pcm_hw_params_any(handle, params);
    // Set the desired hardware parameters.
    // Interleaved mode
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    // Signed 16-bit little-endian format
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    // Two channels (stereo)
    snd_pcm_hw_params_set_channels(handle, params, 2);
    // bits/second sampling rate
    val = 48000;
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
    // Set period size to 32 frames.
    frames = 32;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
    // Write the parameters to the driver
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0) {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        exit(1);
    }
    // Use a buffer large enough to hold one period
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    size = frames * 4; // 2 bytes/sample, 2 channels
    buffer2 = (char *) malloc(size);
    // We want to loop for 25 seconds
    snd_pcm_hw_params_get_period_time(params, &val, &dir);
    // 25 seconds in microseconds divided by period time
    loops = 25000000/val;
    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr));

    // Filling server information
    servaddr.sin_family = AF_INET; //ipv4
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = INADDR_ANY; //Any server
    /********************************************
    *         SEND MSG TO SERVER                *
    ********************************************/
    //sockfd:       File descriptor of socket
    //buffer:       Application buffer cointaining the data to be sent
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:      Size of dest_addr structure
    sendto(sockfd, (const char *)data, strlen(data), MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
    printf("Waiting for audio!!!\n");
    /********************************************
    *         RECIEVE MSG FROM SERVER           *
    ********************************************/
    //sockfd:       file descriptor of socket
    //buffer:       Apllication buffer in which to recieve data
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //src_addr:     Structure containing source address is returned
    //addrlen:      Variable in which size of src_addr structure is returned

    int n, len;
    /* We allocate memory to store the payload of the incoming datagram. */
    char *payload = (char *)malloc(PAYLOAD_SIZE*sizeof(char));

    while(1){

        //We receive datagram
        int bytes_read = recvfrom(sockfd, (void *)payload, PAYLOAD_SIZE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
        fprintf(stderr,"r");
        fflush(stderr);

        // We write the datagram to stdout.
        //write(1, (void *)payload, bytes_read);
        //fprintf(stderr,"w");
        //fflush(stderr);

            while (loops > 0) {
                loops--;

                rc = read(sockfd, buffer2, size); //Read audio file

                if (rc == 0)
                {
                    fprintf(stderr, "end of file on input\n");
                    break;
                }
                else if (rc != size)
                {
                    fprintf(stderr, "short read: read %d bytes\n", rc);
                }
                rc = snd_pcm_writei(handle, buffer2, frames);
                if (rc == -EPIPE)
                {
                    // EPIPE means underrun
                    fprintf(stderr, "underrun occurred\n");
                    snd_pcm_prepare(handle);
                }
                else if (rc < 0)
                {
                    fprintf(stderr, "error from writei: %s\n",
                    snd_strerror(rc));
                }
                else if (rc != (int)frames)
                {
                    fprintf(stderr, "short write, write %d frames\n", rc);
                }
            }
        snd_pcm_drain(handle);
        snd_pcm_close(handle);
        free(buffer2);
        buffer1[n] = '\0';
        printf("Server : %s\n", buffer1);
    }
    //n = recvfrom(sockfd, (char *)buffer1, MAXLINE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
    close(sockfd); //close file descriptor
    return 0;
}
</code>```

server.c

```<code>// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
//CONSTANTS
#define PORT     8080
#define MAXLINE  1024
#define PAYLOAD_SIZE 128

// Driver code
int main(int argc, char *argv[]) {

    int sockfd;
    char buffer[MAXLINE];
    char *msg = "Hello from server, ready to send audio";
    struct sockaddr_in servaddr, cliaddr;
    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { /*AL_INET: ipv4; SOCK_DGRAM: UPD; 0: default protocol*/
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr)); //Allocate memory for structure
    memset(&cliaddr, 0, sizeof(cliaddr));
    // Filling server information
    servaddr.sin_family = AF_INET; // IPv4
    servaddr.sin_addr.s_addr = INADDR_ANY;//Any client
    servaddr.sin_port = htons(PORT);
    /********************************************
    *  BIND THE SOCKET WITH THE SERVER ADDRESS  *
    ********************************************/
    //sockfd:   File descriptor of socket to be binded
    //addr:     Structure in which address to be binded to is specified
    //addrlen:  Size of addr structure
    if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 )
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    /********************************************
    *         RECIEVE MSG FROM CLIENT           *
    ********************************************/
    //sockfd:   file descriptor of socket
    //buffer:   Apllication buffer in which to recieve data
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //src_addr: Structure containing source address is returned
    //addrlen:  Variable in which size of src_addr structure is returned
    int len, n;
    len = sizeof(cliaddr); //len is value/resuslt

    n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);

    buffer[n] = '\0';
    printf("Client : %s\n", buffer);
    /********************************************
    *         SEND MSG TO CLIENT                *
    ********************************************/
    //sockfd:   File descriptor of socket
    //buffer:   Application buffer cointaining the data to be sent
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:  Size of dest_addr structure

    // We allocate memory for the datagrams payload
    char *payload = (char *)malloc(PAYLOAD_SIZE*sizeof(char));

    printf("Sending audio in 3, 2, 1.....\n");

    while(1){
        // Reading from the std in
        int bytes_read = read(0, (void *)payload, PAYLOAD_SIZE);
        fprintf(stderr, "r");
        fflush(stderr);
        if(bytes_read < 1) break;

        // We write the datagram to stdout.
        write(1, (void *)payload, bytes_read);
        fprintf(stderr, "w");
        fflush(stderr);

        //Sending datagram
        sendto(sockfd, (void *)payload, bytes_read, 0, (struct sockaddr *) &cliaddr, len);
        fprintf(stderr, "s");
        fflush(stderr);
    }
    //sendto(sockfd, (const char *)msg, strlen(msg), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len);
    return 0;
}
</code>```

答:
The problem in your implementation is that the transfer of the music data is one way from the server to the client.  When the client sends the first request, the server starts broadcasting the audio stream as fast as it can.  As a result the client will loose some packets.  If only one in two packets gets actually written to the audio device, it looks like that the music is played twice as fast.  You can easily see that you are loosing packets if you sum all the bytes_read in the client.  It will be much smaller than the actual file size.

Also it's not clear why in the client you first recvfrom socket into payload and then read into buffer2.  In theory only the first operation is required and then you write from payload to the audio device.

If you want to implement the streaming in the proper way you need to implement a proper buffering solution in the client and also some speed throttling on the server, to avoid sending data at a speed much higher than needed.

If you want to fix your code in an easy way, one possibility would be to add an ACK that the client sends to the server after receiving one packet.  The server will wait for the client ACK before sending the next packet.  This will more or less make the UDP protocol a TCP protocol.

I have modified your code a little bit to show you what I mwan.  With this code you are able to playback correctly the wav file.  It's not perfect, but at least it should give you an idea of what is the problem with your code

server.c

```<code>// gcc -o server server.c
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

// CONSTANTS
#define PORT            8080
#define MAXLINE         1024
#define PAYLOAD_SIZE    2048

int main(int argc, char *argv[])
{
    int sockfd;
    char buffer[MAXLINE];
    const char* msg = "SERVER: Sending audio complete";

    struct sockaddr_in servaddr, cliaddr;

    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        /*AL_INET: ipv4; SOCK_DGRAM: UPD; 0: default protocol*/
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr));     // Allocate memory for structure
    memset(&cliaddr, 0, sizeof(cliaddr));

    // Filling server information
    servaddr.sin_family = AF_INET;              // IPv4
    servaddr.sin_addr.s_addr = INADDR_ANY;      // Any client
    servaddr.sin_port = htons(PORT);

    /********************************************
    *  BIND THE SOCKET WITH THE SERVER ADDRESS  *
    ********************************************/
    //sockfd:   File descriptor of socket to be binded
    //addr:     Structure in which address to be binded to is specified
    //addrlen:  Size of addr structure
    if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    /********************************************
    *         RECIEVE MSG FROM CLIENT           *
    ********************************************/
    //sockfd:   file descriptor of socket
    //buffer:   Apllication buffer in which to recieve data
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //src_addr: Structure containing source address is returned
    //addrlen:  Variable in which size of src_addr structure is returned
    int len, n;
    len = sizeof(cliaddr);  // len is value/result

    printf("Waiting for client connection...\n");
    n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);

    buffer[n] = '\0';
    printf("%s\n", buffer);

    /********************************************
    *         SEND MSG TO CLIENT                *
    ********************************************/
    //sockfd:   File descriptor of socket
    //buffer:   Application buffer cointaining the data to be sent
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:  Size of dest_addr structure

    // We allocate memory for the datagrams payload
    char* payload = (char*)malloc(PAYLOAD_SIZE * sizeof(char));

    printf("Sending audio...\n");

    while (1) {
        // Reading from the stdin
        int bytes_read = read(0, (void*)payload, PAYLOAD_SIZE);
        if (bytes_read <= 0)
            break;

        // Sending datagram
        sendto(sockfd, (void*)payload, bytes_read, 0, (struct sockaddr *)&cliaddr, len);

        // Waiting for ACK
        n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);
    }

    return 0;
}
</code>```

client.c

```<code>// gcc -o client client.c -lasound

// Remote Radio Head - client side
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <alsa/asoundlib.h>
#include <dirent.h>

/* CONSTANTS */
#define PORT                8080
#define MAXLINE             1024
#define FRAME_SIZE          512
#define PAYLOAD_SIZE        (FRAME_SIZE * 4)

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API

int main(int argc, char *argv[])
{
    // Sockets variables
    int sockfd;
    const char* ACK = "ack";
    const char* START_BROADCAST = "CLIENT: waiting for audio to playback";

    struct sockaddr_in servaddr;

    // ALSA playback variables
    int rc;
    int size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;

    /*********************************************
    *           ALSA DRIVERS SETUP               *
    *********************************************/
    // Open PCM device for playback.
    rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0) {
        fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
        exit(1);
    }
    // Allocate a hardware parameters object.
    snd_pcm_hw_params_alloca(&params);
    // Fill it in with default values.
    snd_pcm_hw_params_any(handle, params);
    // Set the desired hardware parameters.
    // Interleaved mode
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    // Signed 16-bit little-endian format
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    // Two channels (stereo)
    snd_pcm_hw_params_set_channels(handle, params, 2);
    // bits/second sampling rate
    val = 48000;
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
    // Set period size to 32 frames.
    frames = FRAME_SIZE;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
    // Write the parameters to the driver
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0) {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        exit(1);
    }

    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr));

    // Filling server information
    servaddr.sin_family = AF_INET;              // ipv4
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = INADDR_ANY;      // Any server

    /********************************************
    *         SEND MSG TO SERVER                *
    ********************************************/
    //sockfd:       File descriptor of socket
    //buffer:       Application buffer cointaining the data to be sent
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:      Size of dest_addr structure
    sendto(sockfd, START_BROADCAST, strlen(START_BROADCAST), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr));
    printf("Waiting for audio!!!\n");

    /********************************************
    *         RECIEVE MSG FROM SERVER           *
    ********************************************/
    //sockfd:       file descriptor of socket
    //buffer:       Apllication buffer in which to recieve data
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //src_addr:     Structure containing source address is returned
    //addrlen:      Variable in which size of src_addr structure is returned

    int n, len;
    /* We allocate memory to store the payload of the incoming datagram. */
    char *payload = (char *)malloc(PAYLOAD_SIZE * sizeof(char));

    while (1)
    {
        len = PAYLOAD_SIZE;
        int bytes_read = recvfrom(sockfd, (void *)payload, PAYLOAD_SIZE, MSG_WAITALL, (struct sockaddr *)&servaddr, &len);

        rc = snd_pcm_writei(handle, payload, frames);
        if (rc == -EPIPE) {
            // EPIPE means underrun
            fprintf(stderr, "underrun occurred\n");
            snd_pcm_prepare(handle);
        } else if (rc < 0) {
            fprintf(stderr, "error from writei: %s\n",
                    snd_strerror(rc));
        } else if (rc != (int)frames) {
            fprintf(stderr, "short write, write %d frames\n", rc);
        }

        // Send ACK
        sendto(sockfd, ACK, strlen(ACK), 0, (const struct sockaddr *)&servaddr, len);
    }

    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    close(sockfd); //close file descriptor
    return 0;
}

</code>```

Body:
I'm trying to send a .wav file via UDP sockets from the server to the client and playing it back from the client side.

The file is 48kHz and 16 bits and has duration of 25 sec.

Since the server.c  is a small code section inside a larger C-RAN code module I'm checking it by passing a wav file from the stdin:

./SERVER < filename.wav

and then as soon as I execute the client.c, the server starts sending the datagrams and the client.c starts playing them back. Everything is fine bu the audio is played back at a much faster speed, its like playing it back at twice the correct speed. Sometimes it starts playing back correctlyI but after a few seconds it speeds up.

I've  passed a large .txt file instead of the .wav file and the client recieves all the .txt file, from start to end.

Is there anything that I'm missing that I should take into account in order to playback the audio wav file correctly?

client.c code:

// Remote Radio Head - client side
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <alsa/asoundlib.h>
#include <dirent.h>

/* CONSTANTS */
#define PORT     8080
#define MAXLINE  1024
#define PAYLOAD_SIZE 128

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
/*************************************************
*          DRIVER CODE           *
*************************************************/
int main(int argc, char *argv[]) {
    // Sockets variables
    int sockfd;
    char buffer1[MAXLINE];
    char *data = "Hello from client, waiting for audio to playback";
    struct sockaddr_in     servaddr;

    // ALSA playback variables
    long loops;
    int rc;
    int size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;
    char *buffer2;
    /*********************************************
    *           ALSA DRIVERS SETUP               *
    *********************************************/
    // Open PCM device for playback.
    rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0) {
        fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
        exit(1);
    }
    // Allocate a hardware parameters object.
    snd_pcm_hw_params_alloca(&params);
    // Fill it in with default values.
    snd_pcm_hw_params_any(handle, params);
    // Set the desired hardware parameters.
    // Interleaved mode
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    // Signed 16-bit little-endian format
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    // Two channels (stereo)
    snd_pcm_hw_params_set_channels(handle, params, 2);
    // bits/second sampling rate
    val = 48000;
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
    // Set period size to 32 frames.
    frames = 32;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
    // Write the parameters to the driver
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0) {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        exit(1);
    }
    // Use a buffer large enough to hold one period
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    size = frames * 4; // 2 bytes/sample, 2 channels
    buffer2 = (char *) malloc(size);
    // We want to loop for 25 seconds
    snd_pcm_hw_params_get_period_time(params, &val, &dir);
    // 25 seconds in microseconds divided by period time
    loops = 25000000/val;
    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr));

    // Filling server information
    servaddr.sin_family = AF_INET; //ipv4
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = INADDR_ANY; //Any server
    /********************************************
    *         SEND MSG TO SERVER                *
    ********************************************/
    //sockfd:       File descriptor of socket
    //buffer:       Application buffer cointaining the data to be sent
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:      Size of dest_addr structure
    sendto(sockfd, (const char *)data, strlen(data), MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
    printf("Waiting for audio!!!\n");
    /********************************************
    *         RECIEVE MSG FROM SERVER           *
    ********************************************/
    //sockfd:       file descriptor of socket
    //buffer:       Apllication buffer in which to recieve data
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //src_addr:     Structure containing source address is returned
    //addrlen:      Variable in which size of src_addr structure is returned

    int n, len;
    /* We allocate memory to store the payload of the incoming datagram. */
    char *payload = (char *)malloc(PAYLOAD_SIZE*sizeof(char));

    while(1){

        //We receive datagram
        int bytes_read = recvfrom(sockfd, (void *)payload, PAYLOAD_SIZE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
        fprintf(stderr,"r");
        fflush(stderr);

        // We write the datagram to stdout.
        //write(1, (void *)payload, bytes_read);
        //fprintf(stderr,"w");
        //fflush(stderr);

            while (loops > 0) {
                loops--;

                rc = read(sockfd, buffer2, size); //Read audio file

                if (rc == 0)
                {
                    fprintf(stderr, "end of file on input\n");
                    break;
                }
                else if (rc != size)
                {
                    fprintf(stderr, "short read: read %d bytes\n", rc);
                }
                rc = snd_pcm_writei(handle, buffer2, frames);
                if (rc == -EPIPE)
                {
                    // EPIPE means underrun
                    fprintf(stderr, "underrun occurred\n");
                    snd_pcm_prepare(handle);
                }
                else if (rc < 0)
                {
                    fprintf(stderr, "error from writei: %s\n",
                    snd_strerror(rc));
                }
                else if (rc != (int)frames)
                {
                    fprintf(stderr, "short write, write %d frames\n", rc);
                }
            }
        snd_pcm_drain(handle);
        snd_pcm_close(handle);
        free(buffer2);
        buffer1[n] = '\0';
        printf("Server : %s\n", buffer1);
    }
    //n = recvfrom(sockfd, (char *)buffer1, MAXLINE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
    close(sockfd); //close file descriptor
    return 0;
}

server.c

// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
//CONSTANTS
#define PORT     8080
#define MAXLINE  1024
#define PAYLOAD_SIZE 128

// Driver code
int main(int argc, char *argv[]) {

    int sockfd;
    char buffer[MAXLINE];
    char *msg = "Hello from server, ready to send audio";
    struct sockaddr_in servaddr, cliaddr;
    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { /*AL_INET: ipv4; SOCK_DGRAM: UPD; 0: default protocol*/
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr)); //Allocate memory for structure
    memset(&cliaddr, 0, sizeof(cliaddr));
    // Filling server information
    servaddr.sin_family = AF_INET; // IPv4
    servaddr.sin_addr.s_addr = INADDR_ANY;//Any client
    servaddr.sin_port = htons(PORT);
    /********************************************
    *  BIND THE SOCKET WITH THE SERVER ADDRESS  *
    ********************************************/
    //sockfd:   File descriptor of socket to be binded
    //addr:     Structure in which address to be binded to is specified
    //addrlen:  Size of addr structure
    if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 )
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    /********************************************
    *         RECIEVE MSG FROM CLIENT           *
    ********************************************/
    //sockfd:   file descriptor of socket
    //buffer:   Apllication buffer in which to recieve data
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //src_addr: Structure containing source address is returned
    //addrlen:  Variable in which size of src_addr structure is returned
    int len, n;
    len = sizeof(cliaddr); //len is value/resuslt

    n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);

    buffer[n] = '\0';
    printf("Client : %s\n", buffer);
    /********************************************
    *         SEND MSG TO CLIENT                *
    ********************************************/
    //sockfd:   File descriptor of socket
    //buffer:   Application buffer cointaining the data to be sent
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:  Size of dest_addr structure

    // We allocate memory for the datagrams payload
    char *payload = (char *)malloc(PAYLOAD_SIZE*sizeof(char));

    printf("Sending audio in 3, 2, 1.....\n");

    while(1){
        // Reading from the std in
        int bytes_read = read(0, (void *)payload, PAYLOAD_SIZE);
        fprintf(stderr, "r");
        fflush(stderr);
        if(bytes_read < 1) break;

        // We write the datagram to stdout.
        write(1, (void *)payload, bytes_read);
        fprintf(stderr, "w");
        fflush(stderr);

        //Sending datagram
        sendto(sockfd, (void *)payload, bytes_read, 0, (struct sockaddr *) &cliaddr, len);
        fprintf(stderr, "s");
        fflush(stderr);
    }
    //sendto(sockfd, (const char *)msg, strlen(msg), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len);
    return 0;
}

Body:
The problem in your implementation is that the transfer of the music data is one way from the server to the client.  When the client sends the first request, the server starts broadcasting the audio stream as fast as it can.  As a result the client will loose some packets.  If only one in two packets gets actually written to the audio device, it looks like that the music is played twice as fast.  You can easily see that you are loosing packets if you sum all the bytes_read in the client.  It will be much smaller than the actual file size.

Also it's not clear why in the client you first recvfrom socket into payload and then read into buffer2.  In theory only the first operation is required and then you write from payload to the audio device.

If you want to implement the streaming in the proper way you need to implement a proper buffering solution in the client and also some speed throttling on the server, to avoid sending data at a speed much higher than needed.

If you want to fix your code in an easy way, one possibility would be to add an ACK that the client sends to the server after receiving one packet.  The server will wait for the client ACK before sending the next packet.  This will more or less make the UDP protocol a TCP protocol.

I have modified your code a little bit to show you what I mwan.  With this code you are able to playback correctly the wav file.  It's not perfect, but at least it should give you an idea of what is the problem with your code

server.c

// gcc -o server server.c
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

// CONSTANTS
#define PORT            8080
#define MAXLINE         1024
#define PAYLOAD_SIZE    2048

int main(int argc, char *argv[])
{
    int sockfd;
    char buffer[MAXLINE];
    const char* msg = "SERVER: Sending audio complete";

    struct sockaddr_in servaddr, cliaddr;

    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        /*AL_INET: ipv4; SOCK_DGRAM: UPD; 0: default protocol*/
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr));     // Allocate memory for structure
    memset(&cliaddr, 0, sizeof(cliaddr));

    // Filling server information
    servaddr.sin_family = AF_INET;              // IPv4
    servaddr.sin_addr.s_addr = INADDR_ANY;      // Any client
    servaddr.sin_port = htons(PORT);

    /********************************************
    *  BIND THE SOCKET WITH THE SERVER ADDRESS  *
    ********************************************/
    //sockfd:   File descriptor of socket to be binded
    //addr:     Structure in which address to be binded to is specified
    //addrlen:  Size of addr structure
    if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    /********************************************
    *         RECIEVE MSG FROM CLIENT           *
    ********************************************/
    //sockfd:   file descriptor of socket
    //buffer:   Apllication buffer in which to recieve data
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //src_addr: Structure containing source address is returned
    //addrlen:  Variable in which size of src_addr structure is returned
    int len, n;
    len = sizeof(cliaddr);  // len is value/result

    printf("Waiting for client connection...\n");
    n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);

    buffer[n] = '\0';
    printf("%s\n", buffer);

    /********************************************
    *         SEND MSG TO CLIENT                *
    ********************************************/
    //sockfd:   File descriptor of socket
    //buffer:   Application buffer cointaining the data to be sent
    //len:      Size of buffer
    //flags:    Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:  Size of dest_addr structure

    // We allocate memory for the datagrams payload
    char* payload = (char*)malloc(PAYLOAD_SIZE * sizeof(char));

    printf("Sending audio...\n");

    while (1) {
        // Reading from the stdin
        int bytes_read = read(0, (void*)payload, PAYLOAD_SIZE);
        if (bytes_read <= 0)
            break;

        // Sending datagram
        sendto(sockfd, (void*)payload, bytes_read, 0, (struct sockaddr *)&cliaddr, len);

        // Waiting for ACK
        n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);
    }

    return 0;
}

client.c

// gcc -o client client.c -lasound

// Remote Radio Head - client side
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <alsa/asoundlib.h>
#include <dirent.h>

/* CONSTANTS */
#define PORT                8080
#define MAXLINE             1024
#define FRAME_SIZE          512
#define PAYLOAD_SIZE        (FRAME_SIZE * 4)

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API

int main(int argc, char *argv[])
{
    // Sockets variables
    int sockfd;
    const char* ACK = "ack";
    const char* START_BROADCAST = "CLIENT: waiting for audio to playback";

    struct sockaddr_in servaddr;

    // ALSA playback variables
    int rc;
    int size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;

    /*********************************************
    *           ALSA DRIVERS SETUP               *
    *********************************************/
    // Open PCM device for playback.
    rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0) {
        fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
        exit(1);
    }
    // Allocate a hardware parameters object.
    snd_pcm_hw_params_alloca(&params);
    // Fill it in with default values.
    snd_pcm_hw_params_any(handle, params);
    // Set the desired hardware parameters.
    // Interleaved mode
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    // Signed 16-bit little-endian format
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    // Two channels (stereo)
    snd_pcm_hw_params_set_channels(handle, params, 2);
    // bits/second sampling rate
    val = 48000;
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
    // Set period size to 32 frames.
    frames = FRAME_SIZE;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
    // Write the parameters to the driver
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0) {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        exit(1);
    }

    /*********************************************
    *     CREATING SOCKET FILE DESCRIPTOR        *
    *********************************************/
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    memset(&servaddr, 0, sizeof(servaddr));

    // Filling server information
    servaddr.sin_family = AF_INET;              // ipv4
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = INADDR_ANY;      // Any server

    /********************************************
    *         SEND MSG TO SERVER                *
    ********************************************/
    //sockfd:       File descriptor of socket
    //buffer:       Application buffer cointaining the data to be sent
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //dest_addr:    Structure containing address of destination
    //addrlen:      Size of dest_addr structure
    sendto(sockfd, START_BROADCAST, strlen(START_BROADCAST), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr));
    printf("Waiting for audio!!!\n");

    /********************************************
    *         RECIEVE MSG FROM SERVER           *
    ********************************************/
    //sockfd:       file descriptor of socket
    //buffer:       Apllication buffer in which to recieve data
    //len:          Size of buffer
    //flags:        Bitwise OR flags to modify socket behaviour
    //src_addr:     Structure containing source address is returned
    //addrlen:      Variable in which size of src_addr structure is returned

    int n, len;
    /* We allocate memory to store the payload of the incoming datagram. */
    char *payload = (char *)malloc(PAYLOAD_SIZE * sizeof(char));

    while (1)
    {
        len = PAYLOAD_SIZE;
        int bytes_read = recvfrom(sockfd, (void *)payload, PAYLOAD_SIZE, MSG_WAITALL, (struct sockaddr *)&servaddr, &len);

        rc = snd_pcm_writei(handle, payload, frames);
        if (rc == -EPIPE) {
            // EPIPE means underrun
            fprintf(stderr, "underrun occurred\n");
            snd_pcm_prepare(handle);
        } else if (rc < 0) {
            fprintf(stderr, "error from writei: %s\n",
                    snd_strerror(rc));
        } else if (rc != (int)frames) {
            fprintf(stderr, "short write, write %d frames\n", rc);
        }

        // Send ACK
        sendto(sockfd, ACK, strlen(ACK), 0, (const struct sockaddr *)&servaddr, len);
    }

    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    close(sockfd); //close file descriptor
    return 0;
}


来源: stackexchange

问:
Where clauses in flutter firebase streams
I'm setting up a category selector where pressing a certain image changes the category the user is supposed to see. however if the user doesn't pick a category he should see all items.

```<code> FutureBuilder(
          future: _authService.getUserId(),
          builder: (context, snapshot) {
            if (snapshot.hasData)
              return StreamBuilder(
                  stream: _firestore
                      .collection('Item')
                      .where(_category != null ? ('category', isEqualTo: _category) : true)
                      .snapshots(),
</code>```

I was trying to do something like this but it just gives me an error saying it was expecting a bracket somewhere..

Another question I have about this setup is, even if the _categoy changes, would that update the list? or since the stream is already built it won't? and in the latter, how would I come about updating the list with the actual values?

答:
Change it to the following:

```<code>          StreamBuilder(
            stream: _category != null
                ? Firestore.instance
                    .collection('Item')
                    .where("category", isEqualTo: _category)
                    .snapshots()
                : Firestore.instance.collection('Item').snapshots(),
          ),
</code>```

If the _category is not null then use the where clause, else retrieve everything inside Item.

ContentLicense: CC BY-SA 4.0

Body:
I'm setting up a category selector where pressing a certain image changes the category the user is supposed to see. however if the user doesn't pick a category he should see all items.

 FutureBuilder(
          future: _authService.getUserId(),
          builder: (context, snapshot) {
            if (snapshot.hasData)
              return StreamBuilder(
                  stream: _firestore
                      .collection('Item')
                      .where(_category != null ? ('category', isEqualTo: _category) : true)
                      .snapshots(),

I was trying to do something like this but it just gives me an error saying it was expecting a bracket somewhere..

Another question I have about this setup is, even if the _categoy changes, would that update the list? or since the stream is already built it won't? and in the latter, how would I come about updating the list with the actual values?

Body:
Change it to the following:

          StreamBuilder(
            stream: _category != null
                ? Firestore.instance
                    .collection('Item')
                    .where("category", isEqualTo: _category)
                    .snapshots()
                : Firestore.instance.collection('Item').snapshots(),
          ),

If the _category is not null then use the where clause, else retrieve everything inside Item.


问:
How to calculate moving sums of rows of unique observation in R (example provided)?
I have a data.frame called df , and I am trying to count unique devices on a moving hour basis with a gap of 4 minutes as shown in expected_df . I have provided an example below . I did not find any query meeting my requirements , hence this ...

Given data frame

```<code>df<-data.frame(customer=rep("xyz",19),
           device=c("a","a","a","a","a","a","b","b","b","b","b","b","c","c","c","c","c","c","c"),
           local_date=rep("2020-06-04",19),
           local_hour=rep(4,19),
           local_minute=c(1:6,4:9,6:12))
</code>```

Expected data frame

```<code>expected_df<-data.frame(customer=rep("xyz",8),local_hour=rep(4,8),
                    local_date=rep("2020-06-04",8),
                    local_minute_bucket=c("1_5","2_6","3_7","4_9","5_9","6_10","7_11","8_12"),
                    unique_devices=c(2,3,3,3,3,3,2,2))
</code>```

答:
Can't come up with anything better than this.

A function which gives the data for a particular time interval.

```<code>library(dplyr)
library(tidyr)
library(purrr)

Get_data <- function(data, minute) {

  data %>%
    filter(local_minute >= minute & local_minute <= minute + 4) %>%
    summarise(local_minute_bucket = paste(min(local_minute),
                                          max(local_minute), sep = '-'),
              unique_devices = n_distinct(device))
}
</code>```

Split the data based for every date and hour and apply this function for every minute till max - 4 minute.

```<code>df %>%
  group_split(local_date, local_hour) %>%
  map_df(function(data) data %>%
                          group_by(local_date, local_hour) %>%
                          summarise(new = list(map(seq_len(max(local_minute) - 4),
                                    Get_data, data = data)))) %>%
   unnest(new) %>%
   unnest_wider(new)

#  local_date local_hour local_minute_bucket unique_devices
#  <chr>           <dbl> <chr>                        <int>
#1 2020-06-04          4 1-5                              2
#2 2020-06-04          4 2-6                              3
#3 2020-06-04          4 3-7                              3
#4 2020-06-04          4 4-8                              3
#5 2020-06-04          4 5-9                              3
#6 2020-06-04          4 6-10                             3
#7 2020-06-04          4 7-11                             2
#8 2020-06-04          4 8-12                             2
</code>```

Body:
I have a data.frame called df , and I am trying to count unique devices on a moving hour basis with a gap of 4 minutes as shown in expected_df . I have provided an example below . I did not find any query meeting my requirements , hence this ...

Given data frame

df<-data.frame(customer=rep("xyz",19),
           device=c("a","a","a","a","a","a","b","b","b","b","b","b","c","c","c","c","c","c","c"),
           local_date=rep("2020-06-04",19),
           local_hour=rep(4,19),
           local_minute=c(1:6,4:9,6:12))

Expected data frame

expected_df<-data.frame(customer=rep("xyz",8),local_hour=rep(4,8),
                    local_date=rep("2020-06-04",8),
                    local_minute_bucket=c("1_5","2_6","3_7","4_9","5_9","6_10","7_11","8_12"),
                    unique_devices=c(2,3,3,3,3,3,2,2))

Body:
Can't come up with anything better than this.

A function which gives the data for a particular time interval.

library(dplyr)
library(tidyr)
library(purrr)

Get_data <- function(data, minute) {

  data %>%
    filter(local_minute >= minute & local_minute <= minute + 4) %>%
    summarise(local_minute_bucket = paste(min(local_minute),
                                          max(local_minute), sep = '-'),
              unique_devices = n_distinct(device))
}

Split the data based for every date and hour and apply this function for every minute till max - 4 minute.

df %>%
  group_split(local_date, local_hour) %>%
  map_df(function(data) data %>%
                          group_by(local_date, local_hour) %>%
                          summarise(new = list(map(seq_len(max(local_minute) - 4),
                                    Get_data, data = data)))) %>%
   unnest(new) %>%
   unnest_wider(new)

#  local_date local_hour local_minute_bucket unique_devices
#  <chr>           <dbl> <chr>                        <int>
#1 2020-06-04          4 1-5                              2
#2 2020-06-04          4 2-6                              3
#3 2020-06-04          4 3-7                              3
#4 2020-06-04          4 4-8                              3
#5 2020-06-04          4 5-9                              3
#6 2020-06-04          4 6-10                             3
#7 2020-06-04          4 7-11                             2
#8 2020-06-04          4 8-12                             2


问:
How to find fast the number of files in directory?
I have thousands log files in a few directories in my system. Mostly I need to know just number of these files in directory. I fear that this attitude:

```<code>$files = count(scandir("logs")) - 2;
</code>```

Is not very effective (memory, filesystem). I am considering some global counter (incremented after file is added), unless there is some other effective way?

答:
Maybe with opendir/readdir?</p>

```<code><?php
$i = 0;
if ($handle = opendir('.')) {
    while (false !== ($file = readdir($handle))
        if ($file != "." && $file != "..")
            ++$i;
    closedir($handle);
}
?>
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have thousands log files in a few directories in my system. Mostly I need to know just number of these files in directory. I fear that this attitude:

$files = count(scandir("logs")) - 2;

Is not very effective (memory, filesystem). I am considering some global counter (incremented after file is added), unless there is some other effective way?

Body:
Maybe with opendir/readdir?

<?php
$i = 0;
if ($handle = opendir('.')) {
    while (false !== ($file = readdir($handle))
        if ($file != "." && $file != "..")
            ++$i;
    closedir($handle);
}
?>


问:
Drawing Bowling Pins (pyramid) with Recursion in Ada
I know this is pushing the good will of the community by presenting my least elaborate work expecting someone to come and save me but I simply have no choice with nothing to lose. I've gone through packets, files, types, flags and boxes the last few weeks but I haven't covered much of recursion. Especially not drawing with recursion. My exam is in roughly one week and I hope this is ample time to repeat and learn simple recursion tricks like that of drawing bowling pins or other patterns:

```<code>I I I I I
 I I I I
  I I I
   I I
    I
n = 5
</code>```

The problem I have with recursion is that I don't quite get it. How are you supposed to approach a problem like drawing pins like this using recursion?

The closest I've come is

```<code>I I I
I I
I
n = 3
</code>```

and that's using

THIS CODE NOW WORKS

```<code>with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure pyramidchaser is

   subtype X_Type is Integer range 0..30;
   X: X_Type;
   Indent : Integer := 0;

   procedure Numbergrabber (X : out Integer) is
   begin

      Put("Enter a number: ");
      Get(X);
      Skip_Line;
   end Numbergrabber;

   procedure PrintSpaces(I : in Integer) is
   begin
      if I in X_Type then
      Put(" ");
      else
     return;
      end if;

      PrintSpaces(I - 1);
   end Printspaces;

   procedure PrintPins(i, n: in Integer) is
   begin
      if i >= n then
     return;
      end if;

    Put('I');
    Put(' ');

    PrintPins(i + 1, n);
    end Printpins;

   function Pins (X, Indent: in Integer) return Integer is

      Printed : Integer;

   begin

      Printed:= 0;
      if X > 0 then
     PrintSpaces(Indent);
     PrintPins(0, X);
     New_Line;

     Printed := X + Pins(X - 1, Indent + 1);
      end if;
      return Printed;

   end Pins;

   Bowlingpins : Integer;

begin

   Numbergrabber(X);
   Bowlingpins:= Pins(X, Indent);

end pyramidchaser;

</code>```

but with that I throw in a sum I dont really need just to kick off the recursive part which I dont really know why I do except it seems to be needed to be there. I experimented with code from a completely different assignment, thats why it looks the way it does. I know mod 2 will grant me too many new lines but at least it was an approach to finding heights to the pyramid. I understand the real approach is something similar to N+1 as with each step of the growing pyramid a new line is needed, but I dont know how to implement it.

I don't expect anyone to present a complete code but I hope somebody can clue me in on how to think on the way towards finding a solution.

I can still pass the exam without knowing recursion as its typically 2 assignments where one is and one isnt recursion and you need to pass one or the other, but given that I have some time I thought Id give it a chance.

As always, immensely thankful for anyone fighting the good fight!

Seeing this post gathered some attention Id like to expand the pyramid to one a little more complex:

THE PYRAMID PROBLEM 2

hope someone looks at it. I didnt expect so many good answers, I thought why not throw all I have out there.

```<code>Level 1
|=|

Level 2
|===|
||=||
|===|

Level 3

|=====|
||===||
|||=|||
||===||
|=====|

it needs to be figured out recursively. so some way it has to build both upwards and downwards from the center.
</code>```

To clarify Im studying for an exam and surely so are many others whom would be thankful for code to sink their teeth in. Maybe theres an easy way to apply what Tama built in terms of bowling pin lines in pyramid walls?

答:
Bowling pins:

Printing ----I---- is just: (I'm going to use dashes instead of spaces throughout for readability)

Put_Line (4 * "-" & "I" & 4 * "-");
```

<p>And printing the whole bowling triangle could be:</p>

<pre class="lang-pascal prettyprint-override"><code>with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO;       use Ada.Text_IO;

procedure Main is
   procedure Print_Bowling_Line (Dashes : Natural; Pins : Positive) is
      Middle : constant String := (if Pins = 1 then "I"
                                   else (Pins - 1) * "I-" & "I");
   begin
      Put_Line (Dashes * "-" & Middle & Dashes * "-");
   end Print_Bowling_Line;
begin
   Print_Bowling_Line (0, 5);
   Print_Bowling_Line (1, 4);
   Print_Bowling_Line (2, 3);
   Print_Bowling_Line (3, 2);
   Print_Bowling_Line (4, 1);
end Main;
</code>```

Writing the five repeated lines as a loop is quite obvious. For recursion, there are two ways.

Tail recursion

Tail recursion is the more natural 'ask questions, then shoot' approach; first check the parameter for an end-condition, if not, do some things and finally call self.

procedure Tail_Recurse (Pins : Natural) is
begin
   if Pins = 0 then
      return;
   end if;
   Print_Bowling_Line (Total_Pins - Pins, Pins);
   Tail_Recurse (Pins - 1);
end Tail_Recurse;
```

<h3>Head recursion</h3>

<p>Head recursion is what mathematicians love; how do you construct a proof for N? Well, assuming you already have a proof for N-1, you just apply X and you're done. Again, we need to check the end condition before we go looking for a proof for N-1, otherwise we would endlessly recurse and get a stack overflow.</p>

<pre class="lang-pascal prettyprint-override"><code>procedure Head_Recurse (Pins : Natural) is
begin
   if Pins < Total_Pins then
      Head_Recurse (Pins + 1); -- assuming N + 1 proof here
   end if;
   Print_Bowling_Line (Total_Pins - Pins, Pins);
end Head_Recurse;
</code>```

For the full code, expand the following snippet:

with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO;       use Ada.Text_IO;

procedure Main is
   Total_Pins : Natural := 5;

   procedure Print_Bowling_Line (Dashes : Natural; Pins : Positive) is
      Middle : constant String := (if Pins = 1 then "I"
                                   else (Pins - 1) * "I-" & "I");
   begin
      Put_Line (Dashes * "-" & Middle & Dashes * "-");
   end Print_Bowling_Line;

   procedure Tail_Recurse (Pins : Natural) is
   begin
      if Pins = 0 then
         return;
      end if;
      Print_Bowling_Line (Total_Pins - Pins, Pins);
      Tail_Recurse (Pins - 1);
   end Tail_Recurse;

   procedure Head_Recurse (Pins : Natural) is
   begin
      if Pins < Total_Pins then
         Head_Recurse (Pins + 1); -- assuming N + 1 proof here
      end if;
      Print_Bowling_Line (Total_Pins - Pins, Pins);
   end Head_Recurse;
begin
   Total_Pins := 8;
   Head_Recurse (1);
end Main;```
</div>
</div>
</p>

<p>For simplicity, I don't pass around the second number, that indicates the stopping condition, but rather set it once before running the whole.</p>

<p>I always find it unfortunate to try to learn a technique by applying it where it makes the code more complicated, rather than less. So I want to show you a problem where recursion really does shine. Write a program that prints a maze with exactly one path between every two points in the maze, using the following depth-first-search pseudo code:</p>

```start by 'visiting' any field (2,2 in this example)
(recursion starts with this:)
while there are any neighbours that are unvisited,
   pick one at random and
   connect the current field to that field and
   run this procedure for the new field
```

<p>As you can see in the animation below, this should meander randomly until it gets 'stuck' in the bottom left, after which it backtracks to a node that still has an unvisited neighbour. Finally, when everything is filled, all the function calls that are still active will return because for each node there will be no neighbours left to connect to.</p>

<p><img src="https://i.stack.imgur.com/1P7Vh.gif" alt="Maze generation using Depth First Search (backtracking)"></p>

<p>You can use the skeleton code in the snippet below. The answer should only modify the Depth_First_Make_Maze procedure. It need be no longer than 15 lines, calling <code>Get_Unvisited_Neighbours</code>, <code>Is_Empty</code> on the result, <code>Get_Random_Neighbour</code> and <code>Connect</code> (and itself, of course).</p>

<p><div class="snippet" data-lang="js" data-hide="true" data-console="false" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-js lang-js prettyprint-override"><code>with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Containers;                     use Ada.Containers;
with Ada.Containers.Vectors;
with Ada.Numerics.Discrete_Random;

procedure Main is
   N : Positive := 11; -- should be X*2 + 1 for some X >= 1

   type Cell_Status is (Filled, Empty);
   Maze : array (1 .. N, 1 .. N) of Cell_Status := (others => (others => Filled));

   procedure Print_Maze is
   begin
  for Y in 1 .. N loop
     for X in 1 .. N loop
        declare
           C : String := (case Maze (X, Y) is
                             --when Filled => "X", -- for legibility,
                             when Filled => "█", -- unicode block 0x2588 for fun
                             when Empty  => " ");
        begin
           Put (C);
        end;
     end loop;
     Put_Line ("");
  end loop;
   end Print_Maze;

   type Cell_Address is record
  X : Positive;
  Y : Positive;
   end record;

   procedure Empty (Address : Cell_Address) is
   begin
  Maze (Address.X, Address.Y) := Empty;
   end Empty;

   procedure Connect (Address1 : Cell_Address; Address2 : Cell_Address) is
  Middle_X : Positive := (Address1.X + Address2.X) / 2;
  Middle_Y : Positive := (Address1.Y + Address2.Y) / 2;
   begin
  Empty (Address1);
  Empty (Address2);
  Empty ((Middle_X, Middle_Y));
   end Connect;

   function Cell_At (Address : Cell_Address) return Cell_Status is (Maze (Address.X, Address.Y));
   function Left (Address : Cell_Address) return Cell_Address is (Address.X - 2, Address.Y);
   function Right (Address : Cell_Address) return Cell_Address is (Address.X + 2, Address.Y);
   function Up (Address : Cell_Address) return Cell_Address is (Address.X, Address.Y - 2);
   function Down (Address : Cell_Address) return Cell_Address is (Address.X, Address.Y + 2);

   type Neighbour_Count is new Integer range 0 .. 4;
   package Neighbours_Package is new Ada.Containers.Vectors (Index_Type => Natural, Element_Type => Cell_Address);
   use Neighbours_Package;

   function Get_Unvisited_Neighbours (Address : Cell_Address) return Neighbours_Package.Vector is
  NeighbourList : Neighbours_Package.Vector;
   begin
  NeighbourList.Reserve_Capacity (4);
  if Address.X >= 4 then
     declare
        L : Cell_Address := Left (Address);
     begin
        if Cell_At (L) = Filled then
           NeighbourList.Append (L);
        end if;
     end;
  end if;
  if Address.Y >= 4 then
     declare
        U : Cell_Address := Up (Address);
     begin
        if Cell_At (U) = Filled then
           NeighbourList.Append (U);
        end if;
     end;
  end if;
  if Address.X <= (N - 3) then
     declare
        R : Cell_Address := Right (Address);
     begin
        if Cell_At (R) = Filled then
           NeighbourList.Append (R);
        end if;
     end;
  end if;
  if Address.Y <= (N - 3) then
     declare
        D : Cell_Address := Down (Address);
     begin
        if Cell_At (D) = Filled then
           NeighbourList.Append (D);
        end if;
     end;
  end if;
  return NeighbourList;
   end Get_Unvisited_Neighbours;

   package Rnd is new Ada.Numerics.Discrete_Random (Natural);
   Gen : Rnd.Generator;

   function Get_Random_Neighbour (List : Neighbours_Package.Vector) return Cell_Address is
  Random : Natural := Rnd.Random (Gen);
   begin
  if Is_Empty (List) then
     raise Program_Error with "Cannot select any item from an empty list";
  end if;
  declare
     Index : Natural := Random mod Natural (List.Length);
  begin
     return List (Index);
  end;
   end Get_Random_Neighbour;

   procedure Depth_First_Make_Maze (Address : Cell_Address) is
   begin
  null;
   end Depth_First_Make_Maze;
begin
   Rnd.Reset (Gen);
   Maze (1, 2) := Empty; -- entrance
   Maze (N, N - 1) := Empty; -- exit
   Depth_First_Make_Maze ((2, 2));
   Print_Maze;
end Main;</code>```

To see the answer, expand the following snippet.

procedure Depth_First_Make_Maze (Address : Cell_Address) is
begin
   loop
  declare
     Neighbours : Neighbours_Package.Vector := Get_Unvisited_Neighbours (Address);
  begin
     exit when Is_Empty (Neighbours);
     declare
        Next_Node : Cell_Address := Get_Random_Neighbour (Neighbours);
     begin
        Connect (Address, Next_Node);
        Depth_First_Make_Maze (Next_Node);
     end;
  end;
   end loop;
end Depth_First_Make_Maze;```
</div>
</div>
</p>

<h3>Converting recursion to loop</h3>

<p>Consider how a function call works; we take the actual parameters and put them on the call stack along with the function's address. When the function completes, we take those values off the stack again and put back the return value.</p>

<p>We can convert a recursive function by replacing the implicit callstack containing the parameters with an explicit stack. I.e. instead of:</p>

<pre class="lang-pascal prettyprint-override"><code>procedure Foo (I : Integer) is
begin
   Foo (I + 1);
end Foo;
</code>```

We would put I onto the stack, and as long as there are values on the stack, peek at the top value and do the body of the Foo procedure using that value. When there is a call to Foo within that body, push the value you would call the procedure with instead, and restart the loop so that we immediately start processing the new value. If there is no call to self in this case, we discard the top value on the stack.

Restructuring a recursive procedure in this way will give you an insight into how it works, especially since pushing on to the stack is now separated from 'calling' that function since you explicitly take an item from the stack and do something with it.

You will need a stack implementation, here is one that is suitable:

Bounded_Stack.ads

generic
   max_stack_size : Natural;
   type Element_Type is private;
package Bounded_Stack is
   type Stack is private;
   function Create return Stack;
   procedure Push (Onto : in out Stack; Item : Element_Type);
   function Pop (From : in out Stack) return Element_Type;
   function Top (From : in out Stack) return Element_Type;
   procedure Discard (From : in out Stack);
   function Is_Empty (S : in Stack) return Boolean;
   Stack_Empty_Error : exception;
   Stack_Full_Error : exception;
private
   type Element_List is array (1 .. max_stack_size) of Element_Type;
   type Stack is
      record
         list : Element_List;
         top_index : Natural := 0;
      end record;
end Bounded_Stack;
```

<h3>Bounded_Stack.adb</h3>

<pre class="lang-pascal prettyprint-override"><code>package body Bounded_Stack is

   function Create return Stack is
   begin
      return (top_index => 0, list => <>);
   end Create;

   procedure Push (Onto : in out Stack; Item : Element_Type) is
   begin
      if Onto.top_index = max_stack_size then
         raise Stack_Full_Error;
      end if;
      Onto.top_index := Onto.top_index + 1;
      Onto.list (Onto.top_index) := Item;
   end Push;

   function Pop (From : in out Stack) return Element_Type is
      Top_Value : Element_Type := Top (From);
   begin
      From.top_index := From.top_index - 1;
      return Top_Value;
   end Pop;

   function Top (From : in out Stack) return Element_Type is
   begin
      if From.top_index = 0 then
         raise Stack_Empty_Error;
      end if;
      return From.list (From.top_index);
   end Top;

   procedure Discard (From : in out Stack) is
   begin
      if From.top_index = 0 then
         raise Stack_Empty_Error;
      end if;
      From.top_index := From.top_index - 1;
   end Discard;

   function Is_Empty (S : in Stack) return Boolean is (S.top_index = 0);
end Bounded_Stack;
</code>```

It can be instantiated with a maximum stack size of Width*Height, since the worst case scenario is when you happen to choose a non-forking path that visits each cell once:

N_As_Cell_Size : Natural := (N - 1) / 2;
package Cell_Stack is new Bounded_Stack(max_stack_size => N_As_Cell_Size * N_As_Cell_Size, Element_Type => Cell_Address);
```

<p>Take your answer to the previous assignment, and rewrite it without recursion, using the stack above instead.</p>

<p>To see the answer, expand the following snippet.</p>

<p><div class="snippet" data-lang="js" data-hide="true" data-console="false" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-js lang-js prettyprint-override"><code>procedure Depth_First_Make_Maze (Address : Cell_Address) is
   Stack : Cell_Stack.Stack := Cell_Stack.Create;
   use Cell_Stack;
begin
   Push (Stack, Address);
   loop
  exit when Is_Empty (Stack);
  declare
     -- this shadows the parameter, which we shouldn't refer to directly anyway
     Address : Cell_Address := Top (Stack);
     Neighbours : Neighbours_Package.Vector := Get_Unvisited_Neighbours (Address);
  begin
     if Is_Empty (Neighbours) then
        Discard (Stack); -- equivalent to returning from the function in the recursive version
     else
        declare
           Next_Cell : Cell_Address := Get_Random_Neighbour (Neighbours);
        begin
           Connect (Address, Next_Cell);
           Push (Stack, Next_Cell); -- equivalent to calling self in the recursive version
        end;
     end if;
  end;
   end loop;
end Depth_First_Make_Maze;</code>```

Body:
I know this is pushing the good will of the community by presenting my least elaborate work expecting someone to come and save me but I simply have no choice with nothing to lose. I've gone through packets, files, types, flags and boxes the last few weeks but I haven't covered much of recursion. Especially not drawing with recursion. My exam is in roughly one week and I hope this is ample time to repeat and learn simple recursion tricks like that of drawing bowling pins or other patterns:

I I I I I
 I I I I
  I I I
   I I
    I
n = 5

The problem I have with recursion is that I don't quite get it. How are you supposed to approach a problem like drawing pins like this using recursion?

The closest I've come is

I I I
I I
I
n = 3

and that's using

THIS CODE NOW WORKS

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure pyramidchaser is

   subtype X_Type is Integer range 0..30;
   X: X_Type;
   Indent : Integer := 0;

   procedure Numbergrabber (X : out Integer) is
   begin

      Put("Enter a number: ");
      Get(X);
      Skip_Line;
   end Numbergrabber;

   procedure PrintSpaces(I : in Integer) is
   begin
      if I in X_Type then
      Put(" ");
      else
     return;
      end if;

      PrintSpaces(I - 1);
   end Printspaces;

   procedure PrintPins(i, n: in Integer) is
   begin
      if i >= n then
     return;
      end if;

    Put('I');
    Put(' ');

    PrintPins(i + 1, n);
    end Printpins;

   function Pins (X, Indent: in Integer) return Integer is

      Printed : Integer;

   begin

      Printed:= 0;
      if X > 0 then
     PrintSpaces(Indent);
     PrintPins(0, X);
     New_Line;

     Printed := X + Pins(X - 1, Indent + 1);
      end if;
      return Printed;

   end Pins;

   Bowlingpins : Integer;

begin

   Numbergrabber(X);
   Bowlingpins:= Pins(X, Indent);

end pyramidchaser;

but with that I throw in a sum I dont really need just to kick off the recursive part which I dont really know why I do except it seems to be needed to be there. I experimented with code from a completely different assignment, thats why it looks the way it does. I know mod 2 will grant me too many new lines but at least it was an approach to finding heights to the pyramid. I understand the real approach is something similar to N+1 as with each step of the growing pyramid a new line is needed, but I dont know how to implement it.

I don't expect anyone to present a complete code but I hope somebody can clue me in on how to think on the way towards finding a solution.

I can still pass the exam without knowing recursion as its typically 2 assignments where one is and one isnt recursion and you need to pass one or the other, but given that I have some time I thought Id give it a chance.

As always, immensely thankful for anyone fighting the good fight!

Seeing this post gathered some attention Id like to expand the pyramid to one a little more complex:

THE PYRAMID PROBLEM 2

hope someone looks at it. I didnt expect so many good answers, I thought why not throw all I have out there.

Level 1
|=|

Level 2
|===|
||=||
|===|

Level 3

|=====|
||===||
|||=|||
||===||
|=====|

it needs to be figured out recursively. so some way it has to build both upwards and downwards from the center.

To clarify Im studying for an exam and surely so are many others whom would be thankful for code to sink their teeth in. Maybe theres an easy way to apply what Tama built in terms of bowling pin lines in pyramid walls?

Body:
Bowling pins:

Printing ----I---- is just: (I'm going to use dashes instead of spaces throughout for readability)

Put_Line (4 * "-" & "I" & 4 * "-");

And printing the whole bowling triangle could be:

with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO;       use Ada.Text_IO;

procedure Main is
   procedure Print_Bowling_Line (Dashes : Natural; Pins : Positive) is
      Middle : constant String := (if Pins = 1 then "I"
                                   else (Pins - 1) * "I-" & "I");
   begin
      Put_Line (Dashes * "-" & Middle & Dashes * "-");
   end Print_Bowling_Line;
begin
   Print_Bowling_Line (0, 5);
   Print_Bowling_Line (1, 4);
   Print_Bowling_Line (2, 3);
   Print_Bowling_Line (3, 2);
   Print_Bowling_Line (4, 1);
end Main;

Writing the five repeated lines as a loop is quite obvious. For recursion, there are two ways.

Tail recursion

Tail recursion is the more natural 'ask questions, then shoot' approach; first check the parameter for an end-condition, if not, do some things and finally call self.

procedure Tail_Recurse (Pins : Natural) is
begin
   if Pins = 0 then
      return;
   end if;
   Print_Bowling_Line (Total_Pins - Pins, Pins);
   Tail_Recurse (Pins - 1);
end Tail_Recurse;

Head recursion

Head recursion is what mathematicians love; how do you construct a proof for N? Well, assuming you already have a proof for N-1, you just apply X and you're done. Again, we need to check the end condition before we go looking for a proof for N-1, otherwise we would endlessly recurse and get a stack overflow.

procedure Head_Recurse (Pins : Natural) is
begin
   if Pins < Total_Pins then
      Head_Recurse (Pins + 1); -- assuming N + 1 proof here
   end if;
   Print_Bowling_Line (Total_Pins - Pins, Pins);
end Head_Recurse;

For the full code, expand the following snippet:

with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO;       use Ada.Text_IO;

procedure Main is
   Total_Pins : Natural := 5;

   procedure Print_Bowling_Line (Dashes : Natural; Pins : Positive) is
      Middle : constant String := (if Pins = 1 then "I"
                                   else (Pins - 1) * "I-" & "I");
   begin
      Put_Line (Dashes * "-" & Middle & Dashes * "-");
   end Print_Bowling_Line;

   procedure Tail_Recurse (Pins : Natural) is
   begin
      if Pins = 0 then
         return;
      end if;
      Print_Bowling_Line (Total_Pins - Pins, Pins);
      Tail_Recurse (Pins - 1);
   end Tail_Recurse;

   procedure Head_Recurse (Pins : Natural) is
   begin
      if Pins < Total_Pins then
         Head_Recurse (Pins + 1); -- assuming N + 1 proof here
      end if;
      Print_Bowling_Line (Total_Pins - Pins, Pins);
   end Head_Recurse;
begin
   Total_Pins := 8;
   Head_Recurse (1);
end Main;

For simplicity, I don't pass around the second number, that indicates the stopping condition, but rather set it once before running the whole.

I always find it unfortunate to try to learn a technique by applying it where it makes the code more complicated, rather than less. So I want to show you a problem where recursion really does shine. Write a program that prints a maze with exactly one path between every two points in the maze, using the following depth-first-search pseudo code:

start by 'visiting' any field (2,2 in this example)
(recursion starts with this:)
while there are any neighbours that are unvisited,
   pick one at random and
   connect the current field to that field and
   run this procedure for the new field

As you can see in the animation below, this should meander randomly until it gets 'stuck' in the bottom left, after which it backtracks to a node that still has an unvisited neighbour. Finally, when everything is filled, all the function calls that are still active will return because for each node there will be no neighbours left to connect to.

You can use the skeleton code in the snippet below. The answer should only modify the Depth_First_Make_Maze procedure. It need be no longer than 15 lines, calling Get_Unvisited_Neighbours, Is_Empty on the result, Get_Random_Neighbour and Connect (and itself, of course).

with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Containers;                     use Ada.Containers;
with Ada.Containers.Vectors;
with Ada.Numerics.Discrete_Random;

procedure Main is
   N : Positive := 11; -- should be X*2 + 1 for some X >= 1

   type Cell_Status is (Filled, Empty);
   Maze : array (1 .. N, 1 .. N) of Cell_Status := (others => (others => Filled));

   procedure Print_Maze is
   begin
  for Y in 1 .. N loop
     for X in 1 .. N loop
        declare
           C : String := (case Maze (X, Y) is
                             --when Filled => "X", -- for legibility,
                             when Filled => "█", -- unicode block 0x2588 for fun
                             when Empty  => " ");
        begin
           Put (C);
        end;
     end loop;
     Put_Line ("");
  end loop;
   end Print_Maze;

   type Cell_Address is record
  X : Positive;
  Y : Positive;
   end record;

   procedure Empty (Address : Cell_Address) is
   begin
  Maze (Address.X, Address.Y) := Empty;
   end Empty;

   procedure Connect (Address1 : Cell_Address; Address2 : Cell_Address) is
  Middle_X : Positive := (Address1.X + Address2.X) / 2;
  Middle_Y : Positive := (Address1.Y + Address2.Y) / 2;
   begin
  Empty (Address1);
  Empty (Address2);
  Empty ((Middle_X, Middle_Y));
   end Connect;

   function Cell_At (Address : Cell_Address) return Cell_Status is (Maze (Address.X, Address.Y));
   function Left (Address : Cell_Address) return Cell_Address is (Address.X - 2, Address.Y);
   function Right (Address : Cell_Address) return Cell_Address is (Address.X + 2, Address.Y);
   function Up (Address : Cell_Address) return Cell_Address is (Address.X, Address.Y - 2);
   function Down (Address : Cell_Address) return Cell_Address is (Address.X, Address.Y + 2);

   type Neighbour_Count is new Integer range 0 .. 4;
   package Neighbours_Package is new Ada.Containers.Vectors (Index_Type => Natural, Element_Type => Cell_Address);
   use Neighbours_Package;

   function Get_Unvisited_Neighbours (Address : Cell_Address) return Neighbours_Package.Vector is
  NeighbourList : Neighbours_Package.Vector;
   begin
  NeighbourList.Reserve_Capacity (4);
  if Address.X >= 4 then
     declare
        L : Cell_Address := Left (Address);
     begin
        if Cell_At (L) = Filled then
           NeighbourList.Append (L);
        end if;
     end;
  end if;
  if Address.Y >= 4 then
     declare
        U : Cell_Address := Up (Address);
     begin
        if Cell_At (U) = Filled then
           NeighbourList.Append (U);
        end if;
     end;
  end if;
  if Address.X <= (N - 3) then
     declare
        R : Cell_Address := Right (Address);
     begin
        if Cell_At (R) = Filled then
           NeighbourList.Append (R);
        end if;
     end;
  end if;
  if Address.Y <= (N - 3) then
     declare
        D : Cell_Address := Down (Address);
     begin
        if Cell_At (D) = Filled then
           NeighbourList.Append (D);
        end if;
     end;
  end if;
  return NeighbourList;
   end Get_Unvisited_Neighbours;

   package Rnd is new Ada.Numerics.Discrete_Random (Natural);
   Gen : Rnd.Generator;

   function Get_Random_Neighbour (List : Neighbours_Package.Vector) return Cell_Address is
  Random : Natural := Rnd.Random (Gen);
   begin
  if Is_Empty (List) then
     raise Program_Error with "Cannot select any item from an empty list";
  end if;
  declare
     Index : Natural := Random mod Natural (List.Length);
  begin
     return List (Index);
  end;
   end Get_Random_Neighbour;

   procedure Depth_First_Make_Maze (Address : Cell_Address) is
   begin
  null;
   end Depth_First_Make_Maze;
begin
   Rnd.Reset (Gen);
   Maze (1, 2) := Empty; -- entrance
   Maze (N, N - 1) := Empty; -- exit
   Depth_First_Make_Maze ((2, 2));
   Print_Maze;
end Main;

To see the answer, expand the following snippet.

procedure Depth_First_Make_Maze (Address : Cell_Address) is
begin
   loop
  declare
     Neighbours : Neighbours_Package.Vector := Get_Unvisited_Neighbours (Address);
  begin
     exit when Is_Empty (Neighbours);
     declare
        Next_Node : Cell_Address := Get_Random_Neighbour (Neighbours);
     begin
        Connect (Address, Next_Node);
        Depth_First_Make_Maze (Next_Node);
     end;
  end;
   end loop;
end Depth_First_Make_Maze;

Converting recursion to loop

Consider how a function call works; we take the actual parameters and put them on the call stack along with the function's address. When the function completes, we take those values off the stack again and put back the return value.

We can convert a recursive function by replacing the implicit callstack containing the parameters with an explicit stack. I.e. instead of:

procedure Foo (I : Integer) is
begin
   Foo (I + 1);
end Foo;

We would put I onto the stack, and as long as there are values on the stack, peek at the top value and do the body of the Foo procedure using that value. When there is a call to Foo within that body, push the value you would call the procedure with instead, and restart the loop so that we immediately start processing the new value. If there is no call to self in this case, we discard the top value on the stack.

Restructuring a recursive procedure in this way will give you an insight into how it works, especially since pushing on to the stack is now separated from 'calling' that function since you explicitly take an item from the stack and do something with it.

You will need a stack implementation, here is one that is suitable:

Bounded_Stack.ads

generic
   max_stack_size : Natural;
   type Element_Type is private;
package Bounded_Stack is
   type Stack is private;
   function Create return Stack;
   procedure Push (Onto : in out Stack; Item : Element_Type);
   function Pop (From : in out Stack) return Element_Type;
   function Top (From : in out Stack) return Element_Type;
   procedure Discard (From : in out Stack);
   function Is_Empty (S : in Stack) return Boolean;
   Stack_Empty_Error : exception;
   Stack_Full_Error : exception;
private
   type Element_List is array (1 .. max_stack_size) of Element_Type;
   type Stack is
      record
         list : Element_List;
         top_index : Natural := 0;
      end record;
end Bounded_Stack;

Bounded_Stack.adb

package body Bounded_Stack is

   function Create return Stack is
   begin
      return (top_index => 0, list => <>);
   end Create;

   procedure Push (Onto : in out Stack; Item : Element_Type) is
   begin
      if Onto.top_index = max_stack_size then
         raise Stack_Full_Error;
      end if;
      Onto.top_index := Onto.top_index + 1;
      Onto.list (Onto.top_index) := Item;
   end Push;

   function Pop (From : in out Stack) return Element_Type is
      Top_Value : Element_Type := Top (From);
   begin
      From.top_index := From.top_index - 1;
      return Top_Value;
   end Pop;

   function Top (From : in out Stack) return Element_Type is
   begin
      if From.top_index = 0 then
         raise Stack_Empty_Error;
      end if;
      return From.list (From.top_index);
   end Top;

   procedure Discard (From : in out Stack) is
   begin
      if From.top_index = 0 then
         raise Stack_Empty_Error;
      end if;
      From.top_index := From.top_index - 1;
   end Discard;

   function Is_Empty (S : in Stack) return Boolean is (S.top_index = 0);
end Bounded_Stack;

It can be instantiated with a maximum stack size of Width*Height, since the worst case scenario is when you happen to choose a non-forking path that visits each cell once:

N_As_Cell_Size : Natural := (N - 1) / 2;
package Cell_Stack is new Bounded_Stack(max_stack_size => N_As_Cell_Size * N_As_Cell_Size, Element_Type => Cell_Address);

Take your answer to the previous assignment, and rewrite it without recursion, using the stack above instead.

To see the answer, expand the following snippet.

procedure Depth_First_Make_Maze (Address : Cell_Address) is
   Stack : Cell_Stack.Stack := Cell_Stack.Create;
   use Cell_Stack;
begin
   Push (Stack, Address);
   loop
  exit when Is_Empty (Stack);
  declare
     -- this shadows the parameter, which we shouldn't refer to directly anyway
     Address : Cell_Address := Top (Stack);
     Neighbours : Neighbours_Package.Vector := Get_Unvisited_Neighbours (Address);
  begin
     if Is_Empty (Neighbours) then
        Discard (Stack); -- equivalent to returning from the function in the recursive version
     else
        declare
           Next_Cell : Cell_Address := Get_Random_Neighbour (Neighbours);
        begin
           Connect (Address, Next_Cell);
           Push (Stack, Next_Cell); -- equivalent to calling self in the recursive version
        end;
     end if;
  end;
   end loop;
end Depth_First_Make_Maze;


问:
Troubleshooting ML.NET machine learning model issues
I am trying to learn how ML.Net works. I have no experience with machine learning before, so apologies if this is a stupid question.

I have tried to setup a model for candlestick data from stock exchanges. I have loaded the data from the exchange into an enumerable of a class with properties for timestamp, open, high, low, close and volume. (ohlcv are all decimals and timestamp is a DateTime)

When I try to load the list into an IDataView using Context.Data.LoadFromEnumerable

I get the following error:

```<code>ArgumentOutOfRangeException: Could not determine an IDataView type for member High (Parameter 'rawType')
</code>```

I have checked the data and there are no 0 values and its not nullable so I am not sure what the problem is. Can anyone help?

Also, will these feature columns need to be encoded? if so what is the best type of encoding for double values and dates?

Thanks

Paul

答: This is because the decimal type is not supported. It must be converted to a none nullable float. Also call features need to be the same datatype for the model to be trained with the pipeline</p>

Body:
I am trying to learn how ML.Net works. I have no experience with machine learning before, so apologies if this is a stupid question.

I have tried to setup a model for candlestick data from stock exchanges. I have loaded the data from the exchange into an enumerable of a class with properties for timestamp, open, high, low, close and volume. (ohlcv are all decimals and timestamp is a DateTime)

When I try to load the list into an IDataView using Context.Data.LoadFromEnumerable

I get the following error:

ArgumentOutOfRangeException: Could not determine an IDataView type for member High (Parameter 'rawType')

I have checked the data and there are no 0 values and its not nullable so I am not sure what the problem is. Can anyone help?

Also, will these feature columns need to be encoded? if so what is the best type of encoding for double values and dates?

Thanks

Paul


问:
How to replace all the same text inside a blocked text in vim?
How to change this code:

```<code>    dayHour: {
        sunday: {
          openHour: null,
          closeHour: null,
        },
        monday: {
          openHour: null,
          closeHour: null,
        },
        tuesday: {
          openHour: null,
          closeHour: null,
        },
        wednesday: {
          openHour: null,
          closeHour: null,
        },
        thursday: {
          openHour: null,
          closeHour: null,
        },
        ...
     }
</code>```

to this code :

```<code>dayHour: {
    sunday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    monday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    tuesday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    wednesday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    thursday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    ...
  }
</code>```

This is what I've tried, I block the text :

```<code>openHour: null,
closeHour: null
</code>```

and I have no idea what to do next to find and replace the text I've blocked.
I have search several questions on google but I found nothing, and don't even know what keyword to search. Thanks

答:
My attempt using submatch:

```<code>/openHour\_.\{-}clos.*

:%s//\=submatch(0) . "\r          " . substitute(submatch(0), 'Hour', 'Menu', 'g')/g
</code>```

First search using multiline search (non-greedy regex) \_.\{-}. We can reference our search simply by //. After that, we reinsert our search by using submatch(0) plus a newline with some spaces "\r    " then a modified version of our search with substitute.

The dot . is used in order to concatenate our string.

The @matt answer can be changed to:

```<code>:g/closeHour/exec "normal!oopenMenu: null, \<Enter>closeMenu: null"
</code>```

Using double quotes we can use keypresses like \<Enter> instead of the classic ^M that many users do not understand, thus it is more legible. I consider the second @matt solution the right one, it is easier to type and gets right to the point.

Instead of copying the desired text to any register, if it is already on the clipboard we can indicate that with: "+]p, thus it would be:

```<code>:g/closeHour/normal! "+]p
</code>```

Body:
How to change this code:

    dayHour: {
        sunday: {
          openHour: null,
          closeHour: null,
        },
        monday: {
          openHour: null,
          closeHour: null,
        },
        tuesday: {
          openHour: null,
          closeHour: null,
        },
        wednesday: {
          openHour: null,
          closeHour: null,
        },
        thursday: {
          openHour: null,
          closeHour: null,
        },
        ...
     }

to this code :

dayHour: {
    sunday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    monday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    tuesday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    wednesday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    thursday: {
      openHour: null,
      closeHour: null,
      openMenu: null,
      closeMenu: null
    },
    ...
  }

This is what I've tried, I block the text :

openHour: null,
closeHour: null

and I have no idea what to do next to find and replace the text I've blocked.
I have search several questions on google but I found nothing, and don't even know what keyword to search. Thanks

Body:
My attempt using submatch:

/openHour\_.\{-}clos.*

:%s//\=submatch(0) . "\r          " . substitute(submatch(0), 'Hour', 'Menu', 'g')/g

First search using multiline search (non-greedy regex) \_.\{-}. We can reference our search simply by //. After that, we reinsert our search by using submatch(0) plus a newline with some spaces "\r    " then a modified version of our search with substitute.

The dot . is used in order to concatenate our string.

The @matt answer can be changed to:

:g/closeHour/exec "normal!oopenMenu: null, \<Enter>closeMenu: null"

Using double quotes we can use keypresses like \<Enter> instead of the classic ^M that many users do not understand, thus it is more legible. I consider the second @matt solution the right one, it is easier to type and gets right to the point.

Instead of copying the desired text to any register, if it is already on the clipboard we can indicate that with: "+]p, thus it would be:

:g/closeHour/normal! "+]p


问:
How modern X86 processors actually compute multiplications?
I was watching some lecture on algorithms, and the professor used multiplication as an example of how naive algorithms can be improved...

It made me realize that multiplication is not that obvious, although when I am coding I just consider it a simple atomic operation, multiplication requires a algorithm to run, it does not work like summing numbers.

So I wonder, what algorithm modern desktop processors actually use? I guess they don't rely on logarithm tables, and don't make loops with thousands of sums...

答:
Mitch Alsup (who worked on Motorola 88K, Ross SPARC, AMD x86, etc.) has stated on the comp.arch newsgroup:

All modern multiplier designers use the Dadda method for building the tree.

(Message-ID: <c45d9d2e-039d-4085-a617-d90f7a3b1f93@googlegroups.com> — 14 December 2018)

and (with respect to availability of recent references for what multiplication mechanisms are used by AMD/Intel/NVIDIA):

Only in the patent office.

(Message-ID: <d92d1961-a3e4-441e-8b3d-b9ce6bd24b58@googlegroups.com> — 14 January 2020)

See Wikipedia for information on Dadda tree multipliers.


问:
Conditional rendering in React Native with global variable
I know this is horrible convention, but I'm trying to quickly conditionally render screens in my React Native app with global variables (so no redux):

App.js:

```<code>if (global.clickStatus !== 'clicked') {
      return <Screen1 />;
}

return <Screen2 />;
</code>```

The app begins on Screen1, where there is a button that makes global.clickStatus = 'clicked'. When this is clicked, I want Screen2 to render. The problem is, the global.clickStatus doesn't seem to update on my App.js (even though global.clickStatus is changed, it still renders Screen1.

How can I get it to update?

答:
```<code>The app begins on Screen1, where there is a button that makes global.clickStatus = 'clicked'
</code>```

When you click the button, you did not set any state for App.js component => no re-render action is made.
I just assume the button is in Screen 1. Try code below:

import React from "react";
import "./styles.css";

export default function App() {
  // Create a state
  const [renderIndex, setRenderIndex] = useState(new Date().getTime())
  if (global.clickStatus !== 'clicked') {
    // Assume you have a button in Screen1
    // Pass a callback function from this component to Screen1
    // When button in Screen1 is clicked, call this callback function to update renderIndex => App component will re-render
    return <Screen1 callBack={() => setRenderIndex(new Date().getTime())}/>;
}

return <Screen2 />;
}```

Body:
I know this is horrible convention, but I'm trying to quickly conditionally render screens in my React Native app with global variables (so no redux):

App.js:

if (global.clickStatus !== 'clicked') {
      return <Screen1 />;
}

return <Screen2 />;

The app begins on Screen1, where there is a button that makes global.clickStatus = 'clicked'. When this is clicked, I want Screen2 to render. The problem is, the global.clickStatus doesn't seem to update on my App.js (even though global.clickStatus is changed, it still renders Screen1.

How can I get it to update?

Body:
The app begins on Screen1, where there is a button that makes global.clickStatus = 'clicked'

When you click the button, you did not set any state for App.js component => no re-render action is made.
I just assume the button is in Screen 1. Try code below:

import React from "react";
import "./styles.css";

export default function App() {
  // Create a state
  const [renderIndex, setRenderIndex] = useState(new Date().getTime())
  if (global.clickStatus !== 'clicked') {
    // Assume you have a button in Screen1
    // Pass a callback function from this component to Screen1
    // When button in Screen1 is clicked, call this callback function to update renderIndex => App component will re-render
    return <Screen1 callBack={() => setRenderIndex(new Date().getTime())}/>;
}

return <Screen2 />;
}


问:
mongodb array query for search bar
I am trying to return documents where at least one element from the selected field array matches the query array.

I have tried the following queries:

```<code>const match_equipment = await studios.find({equipment: {$eleMatch:{$in: ["mic","amp"]}}});
</code>```

```<code>const match_equipment = await studios.find({equipment: {$all: ["mic","amp"]}});
</code>```

The 1st query gives me "db query failed error" 2nd one gives me "no result found".

Sample document:

```<code>{
    "_id": {"$oid": "5ec5d38be97c8869bee29e78"},
    "equipment": ["guitar", " mic", " amp"],
    "studio_name": "Best recordings",
    "email": "changed@gmail.com",
    "address": "34 harming st. Brunswick",
    "postcode": "3056",
    "price": "50",
    "__v": {"$numberInt": "0"},
    "unavalibility": [
        {
            "times": [{"$numberInt": "13"}],
            "_id": {"$oid": "5ec610e47cf2fb4e84ba0c54"}, "date": {"$date": {"$numberLong": "1591920000000"}}
        }
    ]
}
</code>```

答:
You are very close, you just have a syntax error.

It's $elemMatch and not eleMatch

So changing it will work:

```<code>const match_equipment = await studios.find({equipment: {$elemMatch:{$in: ["mic","amp"]}}});
</code>```

But the essence of $elemMatch is more specialised queries. Which in your case are not required. So you can just use the following version utilizing $in only:

```<code>const match_equipment = await studios.find({equipment: {$in: ["mic","amp"]}});
</code>```

Title: mongodb array query for search bar

Body:
I am trying to return documents where at least one element from the selected field array matches the query array.

I have tried the following queries:

const match_equipment = await studios.find({equipment: {$eleMatch:{$in: ["mic","amp"]}}});

const match_equipment = await studios.find({equipment: {$all: ["mic","amp"]}});

The 1st query gives me "db query failed error" 2nd one gives me "no result found".

Sample document:

{
    "_id": {"$oid": "5ec5d38be97c8869bee29e78"},
    "equipment": ["guitar", " mic", " amp"],
    "studio_name": "Best recordings",
    "email": "changed@gmail.com",
    "address": "34 harming st. Brunswick",
    "postcode": "3056",
    "price": "50",
    "__v": {"$numberInt": "0"},
    "unavalibility": [
        {
            "times": [{"$numberInt": "13"}],
            "_id": {"$oid": "5ec610e47cf2fb4e84ba0c54"}, "date": {"$date": {"$numberLong": "1591920000000"}}
        }
    ]
}

Body:
You are very close, you just have a syntax error.

It's $elemMatch and not eleMatch

So changing it will work:

const match_equipment = await studios.find({equipment: {$elemMatch:{$in: ["mic","amp"]}}});

But the essence of $elemMatch is more specialised queries. Which in your case are not required. So you can just use the following version utilizing $in only:

const match_equipment = await studios.find({equipment: {$in: ["mic","amp"]}});


问:
How do you put an onclick on a js button
I have some js created buttons from GeeksforGeeks, but I don't know how to put on click on the buttons. I can create a button using the code I found online, but there was no explanation on how to make that button have on click function</p>

答:
It is as simple as below: </p>

```<code><button id="submit" value="Submit" onclick="getData();">Submit</button>

function getData(){
// your logic

}
</code>```

Body:
It is as simple as below:

<button id="submit" value="Submit" onclick="getData();">Submit</button>

function getData(){
// your logic

}