Search code examples
cparsingtextlineskip

Parse Text File in C - Skip Lines - Repeated Calculation


I have been spinning my wheels for a while trying to figure this out but have not been able to. Hope you can help!

I am currently working on a program that solves Sudoku. The current code that I am showing below takes in as input a 9x9 grid of integers (the Sudoku puzzle) and then generates a solution. This is working fine.

#include <stdio.h>

int isAvailable(int puzzle[][9], int row, int col, int num)
{
    int rowStart = (row/3) * 3;
    int colStart = (col/3) * 3;
    int i, j;

    for(i=0; i<9; ++i)
    {
        if (puzzle[row][i] == num) return 0;
        if (puzzle[i][col] == num) return 0;
        if (puzzle[rowStart + (i%3)][colStart + (i/3)] == num) return 0;
    }
    return 1;
}

int fillSudoku(int puzzle[][9], int row, int col)
{
    int i;
    if(row<9 && col<9)
    {
        if(puzzle[row][col] != 0)
        {
            if((col+1)<9) return fillSudoku(puzzle, row, col+1);
            else if((row+1)<9) return fillSudoku(puzzle, row+1, 0);
            else return 1;
        }
        else
        {
            for(i=0; i<9; ++i)
            {
                if(isAvailable(puzzle, row, col, i+1))
                {
                    puzzle[row][col] = i+1;
                    if((col+1)<9)
                    {
                        if(fillSudoku(puzzle, row, col +1)) return 1;
                        else puzzle[row][col] = 0;
                    }
                    else if((row+1)<9)
                    {
                        if(fillSudoku(puzzle, row+1, 0)) return 1;
                        else puzzle[row][col] = 0;
                    }
                    else return 1;
                }
            }
        }
        return 0;
    }
    else return 1;
}

int main()
{
    int i, j;
    int row,column;
    int puzzle[9][9];
    //printf("Enter your input:\n");
    for (row=0; row <9; row++){
       for(column = 0; column <9; column ++){
       scanf("%d",&puzzle[row][column]);
       }
    }

    //PRINT INPUT PUZZLE
    printf("Original Puzzle:");
    printf("\n+-----+-----+-----+\n");
    for(i=1; i<10; ++i)
    {
        for(j=1; j<10; ++j) printf("|%d", puzzle[i-1][j-1]);
        printf("|\n");
        if (i%3 == 0) printf("+-----+-----+-----+\n");
    }
    printf("\n");


    //PRINT OUTPUT PUZZLE
    printf("Solved Puzzle:");
    if(fillSudoku(puzzle, 0, 0))
    {
        printf("\n+-----+-----+-----+\n");
        for(i=1; i<10; ++i)
        {
            for(j=1; j<10; ++j) printf("|%d", puzzle[i-1][j-1]);
            printf("|\n");
            if (i%3 == 0) printf("+-----+-----+-----+\n");
        }
        printf("\n");
    }

    else printf("\n\nNO SOLUTION\n\n");

    return 0;
}

I now want to use a text file from Project Euler (https://projecteuler.net/project/resources/p096_sudoku.txt) and have my program generate all 50 of these solutions. The text file has the following format:

Grid 01
003020600
900305001
001806400
008102900
700000008
006708200
002609500
800203009
005010300
Grid 02
200080300
060070084
030500209
000105408
000000000
402706000
301007040
720040060
004010003
...

and so on for 50 total grids.

My question is: What is the best way to parse through this file to

  1. Skip over the "Grid ##" line
  2. Read in the next 9 lines for input
  3. Continue on through the file to repeat the program until the end of the file

EDIT: Between steps 2 & 3, this is what would happen: After I read in 9 lines of numbers, I'll use that as input to the program and have the program run and generate a solution, and then look back to the input file and get the next set of numbers and run another iteration of the program.

Thank you for any input and guidance you can provide me! -Colton


Solution

  • When data in a text file is line formatted, strongly recommend using fgets().

    Consider each group of 10 lines as a record. They belong together, if 1 part is in error, the whole group is invalid.

    // return 0 on success, -1 on EOF and 1 on format failure
    int ReadPuzzle(FILE *inf, int puzzle[][9], int *Grid) {
      char buffer[20]; // About 2x expected need
    
      if (fgets(buffer, sizeof buffer, inf) == NULL)
        return -1;  // File EOF or IO error occurred.
      if (sscanf(buffer, "Grid %d", Grid) != 1)
        return 1;
    
      for (int row = 0; row < 9; row++) {
        if (fgets(buffer, sizeof buffer, inf) == NULL)
          return 1;  // If Grid line exists, 9 lines _should_ follow
        char *p = buffer;
        for (int col = 0; col < 9; col++) {
          // Use %1d to limit scanning to 1 digit
          if (sscanf(p, "%1d", &puzzle[row][col]) != 1)
            return 1;
          p++;
        }
      }
      return 0;
    }
    

    Checks could be added to insure extra data is not on the lines.