Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

/prog/ challenge n+1: My other car

Name: Anonymous 2021-03-26 16:54

The goal

The goal is to implement LISP's car/cdr[1] family of functions. Write a program that receives two inputs on the standard input, separated by spaces: the first (cudder) is an accessor in the form of ``c[ad]{0,32}r''. The second is a LISP-style sexp[2], containing integers, potentially nested. Your program should execute the cudder on the sexp and print the result to standard output.

Assumptions

* The cudder will always be provided in such a way that the result is non-NIL/non-NuRuPo.
* Maximum nesting level is 8 levels deep.

Examples

./cudder cdr "(1 2 3 4)"
(2 3 4)
./cudder car "(1 2 3 4)"
1
./cudder cddr "(1 2 3 4)"
(3 4)
./cudder cdddr "(1 2 3 4)"
(4)
./cudder cadr "(1 2 3 4)"
2
./cudder car "((1) 2 3 4)"
(1)
./cudder caar "((1) 2 3 4)"
1
./cudder cadr "(1 (2 3 4))"
(2 3 4)


[1] https://en.wikipedia.org/wiki/CAR_and_CDR
[2] https://en.wikipedia.org/wiki/S-expression#Use_in_Lisp

Name: >>25 2021-03-31 6:27

Ok here's mine:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
int valCar;
struct Node *car;
struct Node *cdr;
} Node;

struct Node * makeNode() {
return (struct Node *) malloc(sizeof(Node));
}

void parse(char **s, struct Node **n) {
while(**s)
switch(**s) {
case ')':
free(*n);
*n = NULL;
(*s)++;
return;
case ' ':
(*s)++;
continue;
case '(':
(*s)++;
(*n)->car = makeNode();
parse(s, &((*n)->car));
(*n)->cdr = makeNode();
n = &((*n)->cdr);
break;
default:
(*n)->valCar = strtol(*s, s, 10);
(*n)->cdr = makeNode();
n = &((*n)->cdr);
}
}

int printList(Node *n) {
if (!n->cdr) {
if (n->car) {
printf("(");
printList(n->car);
printf(")");
}
else {
printf("%d", n->valCar);
printf(")");
}
}
else if (n->car) {
printf("(");
printList(n->car);
printf(" ");
printList(n->cdr);
}
else {
printf("%d", n->valCar);
if (n->cdr) printf(" ");
printList(n->cdr);
}
return 0;
}

int format(Node *n) {
printf("(");
printList(n);
return printf("\n");
}

void eval(char *s, Node *n) {
int i = strlen(++s) - 1;
while (i-- > 1) {
n = (s[i] == 'a') ? n->car : n->cdr;
}
if (s[i] == 'a')
(!n->car) ? printf("%d\n", n->valCar) : format(n->car);
else
(n->cdr) ? format(n->cdr) : printf("()\n");
}

int main(int argc, char **argv) {
if (argc < 3) {
printf("Usage: ./cudder c[ad]+r <list>\n");
return 1;
}
struct Node *res = (struct Node *) malloc(sizeof(Node));
res->car = NULL;
res->cdr = NULL;
char *arg = argv[1];
char **s = &argv[2];
while (*(*s)++ == ' ');
parse(s, &res);
eval(arg, res);
}

Name: >>25 2021-03-31 6:31

Some tests: it handles random white spaces nicely.
$ gcc -o cudder -Wall -pedantic -Wextra cudder.c
$ ./cudder cadr "(1 (2 3 4))"
(2 3 4)
$ ./cudder cdr "(1)"
()
$ ./cudder caddadaaddr " (((((( ((((((((((1))))))))))))))) (( 2 3)) (( 4 (5 6 7)))) "
7
$ time ./cudder cadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddr "(1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0)"
0

real 0m0.001s
user 0m0.001s
sys 0m0.000s
$ time ./cudder caaaaaaaaaaaaaaaar "((((((((((((((((1))))))))))))))))"
1

real 0m0.001s
user 0m0.001s
sys 0m0.000s

Name: Anonymous 2021-03-31 6:43

inb4: I don't intend to collect garbage, it's a simple tree traversal

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List