Skip to content

Instantly share code, notes, and snippets.

@harieamjari
Created February 27, 2021 12:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harieamjari/2ee9c7b119642ced6ddb6374a81908d9 to your computer and use it in GitHub Desktop.
Save harieamjari/2ee9c7b119642ced6ddb6374a81908d9 to your computer and use it in GitHub Desktop.
/* REPLY CHALLENGE
*
* Minimal deterministic parser
*/
#include <stdio.h>
#include <stdlib.h>
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
#define UNEXPECTED(x) {\
if (x!=TOK_ERR) \
ERROR("[%s @ %d] %s:%d:%d error: unexpected %s\n", __FILE__, __LINE__,\
fname, line_token_found, column_token_found, tok_to_str(x)); \
fclose(fp);\
return 1; \
}
#define EXPECTING(x) {\
if (x!=TOK_ERR) \
ERROR("[%s @ %d] %s:%d:%d error: expecting %s\n", __FILE__, __LINE__,\
fname, line_token_found, column_token_found, tok_to_str(x)); \
fclose(fp);\
return 1; \
}
typedef enum token_t token_t;
enum token_t
{
TOK_NUM,
TOK_NEWLINE,
TOK_EOF,
TOK_ERR
};
int line_token_found;
int column_token_found;
int tok_num;
FILE *fp;
char *fname;
char *
tok_to_str (token_t t)
{
switch (t)
{
case TOK_NEWLINE:
return "newline";
case TOK_NUM:
return "numeric";
case TOK_EOF:
return "end of file";
default:
return "internal err!";
}
}
/*-------.
|scanner|
`------*/
token_t
lex (void)
{
static int line = 1;
static int column = 1;
int c;
char buff[100] = { 0 };
/* eat whitespace */
while ((c = fgetc (fp)) == (int) ' ')
column++;
if (c == (int) '\n')
{
column = 1;
line++;
return TOK_NEWLINE;
}
line_token_found = line;
column_token_found = column;
switch (c)
{
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
ungetc (c, fp);
int _column;
fscanf (fp, "%d%n", &tok_num, &_column);
column += _column;
return TOK_NUM;
}
case EOF:
return TOK_EOF;
default:
ERROR ("%s:%d:%d \x1b[1;31merror\x1b[0m:"
" illegal character '%c'\n", fname, line_token_found,
column_token_found, c);
return TOK_ERR;
}
}
int
main (int argc, char **argv)
{
if (argc != 2)
{
ERROR ("syntax: %s [infile]\n", argv[0]);
return 1;
}
fname = argv[1];
fp = fopen (argv[1], "r");
if (fp == NULL)
{
perror (argv[1]);
return 1;
}
token_t tok;
int state_case;
int friends;
int k;
int flag = 1;
/* start parsing */
while ((tok = lex ()) == TOK_NEWLINE);
if (tok != TOK_NUM)
UNEXPECTED (tok);
state_case = tok_num;
for (int ccase = 0; ccase < state_case; ccase++)
{
while ((tok = lex ()) == TOK_NEWLINE);
if (tok != TOK_NUM)
EXPECTING (TOK_NUM);
friends = tok_num;
while ((tok = lex ()) == TOK_NEWLINE);
int buff[1000];
memset (buff, 0, 1000);
for (int i = 0; i < friends; i++)
{
if (tok != TOK_NUM)
EXPECTING (TOK_NUM);
buff[i] = tok_num;
tok = lex ();
}
int num = 0;
int k = 0;
int flag;
while (1)
{
flag = 0;
num = 0;
for (int i = 0; i < friends; i++)
{
if (!buff[i])
{
if (num)
{
num = 0;
break;
}
continue;
}
flag = 1;
buff[i]--;
num = 1;
}
k++;
if (!flag)
break;
}
if (tok != TOK_NEWLINE)
EXPECTING (TOK_NEWLINE);
printf ("Case #%d: %d\n", ccase + 1, k - 1);
}
while ((tok = lex ()) == TOK_NEWLINE);
if (tok != TOK_EOF)
UNEXPECTED (tok);
fclose (fp);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment