Yet another brute force sudoku solver

Discussion in 'C Programming' started by Boon, Oct 16, 2008.

  1. Boon

    Boon Guest

    Hello group,

    I've been toying with a simple sudoku[1] solver. I meant for the code to
    be short and easy to understand. I figured "brute force is simple" --
    who needs finesse, when you've got muscle, right? :)

    [1] http://en.wikipedia.org/wiki/Sudoku

    Thus, the strategy is to test every legal "move" and to backtrack when
    stuck. A recursive function seemed appropriate. I'd like to hear
    comments and suggestions regarding the implementation.

    Regards.

    #include <stdio.h>

    static int grid[9][9];

    void read_grid(FILE *fp)
    {
    int i,j;
    for (i=0; i < 9; ++i)
    {
    char buf[16];
    fgets(buf, sizeof buf, fp);
    for (j=0; j < 9; ++j)
    {
    char c = buf[j];
    if ('1' <= c && c <= '9') grid[j] = c - '0';
    }
    }
    }

    void write_grid(void)
    {
    int i, j;
    for (i=0; i < 9; ++i)
    {
    for (j=0; j < 9; ++j) printf("%d ", grid[j]);
    putchar('\n');
    }
    }

    int is_legal(int row, int col, int val)
    {
    int ii = row - row%3;
    int jj = col - col%3;
    int i, j, k = 0, res = 1;
    for (i=0; i < 3; ++i)
    for (j=0; j < 3; ++j, ++k)
    res = res && (grid[row][k] != val) && (grid[k][col] != val) &&
    (grid[ii+i][jj+j] != val);
    return res;
    }

    void solve(int pos)
    {
    if (pos == 9*9) write_grid();
    else
    {
    int row, col, val;
    row = pos / 9;
    col = pos % 9;
    if (grid[row][col] != 0) solve(pos+1);
    else
    {
    for (val=1; val <= 9; ++val)
    {
    if (is_legal(row, col, val))
    {
    grid[row][col] = val;
    solve(pos+1);
    }
    }
    grid[row][col] = 0;
    }
    }
    }

    int main(void)
    {
    read_grid(stdin);
    solve(0);
    return 0;
    }
     
    Boon, Oct 16, 2008
    #1
    1. Advertising

  2. Boon

    Boon Guest

    Trent Josephsen wrote:

    > Boon wrote:
    >
    >> I've been toying with a simple sudoku[1] solver. I meant for the code
    >> to be short and easy to understand. I figured "brute force is simple"
    >> -- who needs finesse, when you've got muscle, right? :)
    >>
    >> [1] http://en.wikipedia.org/wiki/Sudoku
    >>
    >> Thus, the strategy is to test every legal "move" and to backtrack when
    >> stuck. A recursive function seemed appropriate. I'd like to hear
    >> comments and suggestions regarding the implementation.
    >>
    >> #include <stdio.h>
    >>
    >> static int grid[9][9];

    >
    > Generally you want to avoid global variables, as you probably know.


    I didn't want is_legal() and solve() to require an additional parameter.
    (I know this is not a very convincing reason.)

    >> void read_grid(FILE *fp)
    >> {
    >> int i,j;
    >> for (i=0; i < 9; ++i)
    >> {
    >> char buf[16];
    >> fgets(buf, sizeof buf, fp);

    >
    > Wait, you're reading 16 characters in 9 times? At most you will have
    > eleven (9 characters plus a newline and '\0').


    I'm reading *at most* 16 characters (which should never happen).
    NB : I didn't focus on the I/O routines, they may have holes.

    BTW, in cygwin, the line ends with 0x0d 0x0a 0x00.
    <pedantic mode>
    Is it possible for a platform to "define" '\n' as a sequence of 10
    characters ? Thereby making my buf too small to hold 9 characters,
    newline, and nul.
    </mode>

    >> for (j=0; j < 9; ++j)
    >> {
    >> char c = buf[j];
    >> if ('1' <= c && c <= '9') grid[j] = c - '0';

    >
    > Why bother changing each character (range '1' to '9') to an int (range 1
    > to 9)? It isn't really necessary -- you only need to test if two
    > characters are equal, not do any kind of math with them. Not with the
    > brute force attack, anyway.


    You're right. I'd just have to change the for loop in solve() to
    for (val='1'; val <= '9'; ++val)

    But this wouldn't buy much, either in simplicity or performance, don't
    you agree ?

    >> void solve(int pos)
    >> {
    >> if (pos == 9*9) write_grid();

    >
    > It's probably better to return a code indicating success than to print
    > out the result from solve(), in case you want to do something with that
    > in main(), like print out a different message depending on the result.


    I see your point.

    >> else
    >> {
    >> int row, col, val;
    >> row = pos / 9;
    >> col = pos % 9;
    >> if (grid[row][col] != 0) solve(pos+1);
    >> else
    >> {
    >> for (val=1; val <= 9; ++val)
    >> {
    >> if (is_legal(row, col, val))
    >> {
    >> grid[row][col] = val;
    >> solve(pos+1);

    >
    > What if this call to solve() succeeds?


    What does it mean for a call to succeed ?

    > Does it stop recursing? No, it
    > just returns /and continues testing all the other possibilities/. This
    > could mean that you get more than one printout if there is more than one
    > legal solution. Could be good, could be bad.


    This is by design. I want to see whether a problem has multiple solutions.

    > I'm really not liking this implementation because there's no way for the
    > calling function to know whether the call to solve() succeeded.


    By "succeed" do you mean find one solution or find all solutions or
    something else ? Failing would mean not finding any solution ?

    > In solve() this is bad because when it does succeed the previous level of
    > recursion has no way of knowing that and continues searching for
    > solutions (which may or may not exist), and prints them out as it comes
    > to them. In main() this is bad because you have no way of discerning in
    > the code whether the puzzle is solvable or not.


    I'll keep your comments in mind.

    > It occurs to me that you may want to know all the possible solutions of
    > a particular puzzle; in that case you could let each call return the
    > number of ways it found to solve the problem. This would need a
    > variable that increments each time a solution is found. In any case,
    > this function would be much more practical if you could tell whether it
    > succeeded or not.


    If it were to be used as a library function for example ?

    Regards.
     
    Boon, Oct 16, 2008
    #2
    1. Advertising

  3. Boon

    Guest

    In article <48f771c1$0$8536$>,
    Boon <root@localhost> wrote:
    >Trent Josephsen wrote:
    >
    >> Boon wrote:


    >> Generally you want to avoid global variables, as you probably know.

    >
    >I didn't want is_legal() and solve() to require an additional parameter.
    >(I know this is not a very convincing reason.)


    The important thing to remember about global variables is that *every*
    global is part of the interface to *every* function in your program.
    (Even if it doesn't use it now, there's nothing to stop it from
    deciding to use it at some point in the future.)

    If the program is small and self-contained, and the information you're
    making global is something that the whole program needs, this will
    probably be what you want. But small and self-contained programs have
    an annoying habit of not wanting to stay small and self-contained.
    Sooner or later you'll find yourself wishing that a program that was
    written that way had "all the stuff everybody wants" arguments to its
    functions so you could put it in a larger program as a module and use
    that module for two things at once. So if you're going to use global
    variables, at least keep that in mind, and make it easy to convert it
    into that form later.

    When I use globals, I like to wrap them all up in a small number of
    structs. This has two benefits:
    (1) It makes it easier to transform globals into pass-around-to-
    everybody non-global data; just have everything that needs it (or,
    transitively, calls something that needs it) take a pointer to a
    struct of the appropriate type. Finding functions that need it and
    converting them to use the non-global form is easy - just do a
    search for the global struct name, and make the appropriate changes
    everywhere it shows up.
    (2) It makes it obvious everywhere you use a global variable that this
    is a global you're using. That gives you clues about where to look
    for more information about it, and reminds you to be careful about
    changes there that may affect other chunks of code in completely
    different places.




    >BTW, in cygwin, the line ends with 0x0d 0x0a 0x00.
    ><pedantic mode>
    >Is it possible for a platform to "define" '\n' as a sequence of 10
    >characters ? Thereby making my buf too small to hold 9 characters,
    >newline, and nul.
    ></mode>


    No.
    Well, maybe, but not in a way that affects you.
    The platform is allowed to define "end of line in text files" however
    it wants; but if you open the file in text mode, it's required to
    convert each line from whatever the "native" format is into "sequence
    of characters followed by '\n'", which is the internal representation
    that a C program uses.

    (Note that, on the other side of the stdio library, newline doesn't
    even need to be represented by a (sequence of) character(s);
    f'rexample, an implementation can use fixed-length space-padded lines,
    and that implementation's stdio library would need to read the line,
    trim trailing space padding, and insert '\n' between lines before
    passing the data on to a C program.)

    (This means that if you haven't opened the file in binary mode and
    cygwin is giving you "\r\n" at the end of your lines, then either it's
    failing to do end-of-line translation properly or it's defining
    end-of-line differently than the rest of the system it lives in and
    refusing to play nicely.)



    dave

    --
    Dave Vandervies dj3vande at eskimo dot com
    I'm probably getting senile, but I increasingly tend to regard C as a better
    C++, in the spirit of Hoare's remark about Algol 60 being an improvement on
    nearly all its successors. --Andrew Simmons in comp.lang.c
     
    , Oct 16, 2008
    #3
  4. Boon

    Default User Guest

    Trent Josephsen wrote:

    > Boon wrote:


    > > #include <stdio.h>
    > >
    > > static int grid[9][9];

    >
    > Generally you want to avoid global variables, as you probably know.


    I disagree. This is a perfect usage for file scope (NOT global) data
    constructs. I've been using that sort of thing for my game programming
    some lately. It's a sort of data encapsulation model.




    Brian
     
    Default User, Oct 16, 2008
    #4
  5. Boon

    Richard Guest

    "Default User" <> writes:

    > Trent Josephsen wrote:
    >
    >> Boon wrote:

    >
    >> > #include <stdio.h>
    >> >
    >> > static int grid[9][9];

    >>
    >> Generally you want to avoid global variables, as you probably know.

    >
    > I disagree. This is a perfect usage for file scope (NOT global) data
    > constructs. I've been using that sort of thing for my game programming
    > some lately. It's a sort of data encapsulation model.
    >
    >
    >
    >
    > Brian


    Frankly I think that is nonsense.

    If efficiency was the issue he could simply malloc one bunch of result
    containers or use in function statics to effectively hide things.

    And file scope IS global (as anyone without a rod up their arse knows
    it) since anyone can declare an extern and then see it.
     
    Richard, Oct 16, 2008
    #5
  6. Boon

    user923005 Guest

    On Oct 16, 7:08 am, Boon <root@localhost> wrote:
    > Hello group,
    >
    > I've been toying with a simple sudoku[1] solver. I meant for the code to
    > be short and easy to understand. I figured "brute force is simple" --
    > who needs finesse, when you've got muscle, right? :)
    >
    > [1]http://en.wikipedia.org/wiki/Sudoku
    >
    > Thus, the strategy is to test every legal "move" and to backtrack when
    > stuck. A recursive function seemed appropriate. I'd like to hear
    > comments and suggestions regarding the implementation.
    >
    > Regards.
    >
    > #include <stdio.h>
    >
    > static int grid[9][9];
    >
    > void read_grid(FILE *fp)
    > {
    >    int i,j;
    >    for (i=0; i < 9; ++i)
    >    {
    >      char buf[16];
    >      fgets(buf, sizeof buf, fp);
    >      for (j=0; j < 9; ++j)
    >      {
    >        char c = buf[j];
    >        if ('1' <= c && c <= '9') grid[j] = c - '0';
    >      }
    >    }
    >
    > }
    >
    > void write_grid(void)
    > {
    >    int i, j;
    >    for (i=0; i < 9; ++i)
    >    {
    >      for (j=0; j < 9; ++j) printf("%d ", grid[j]);
    >      putchar('\n');
    >    }
    >
    > }
    >
    > int is_legal(int row, int col, int val)
    > {
    >    int ii = row - row%3;
    >    int jj = col - col%3;
    >    int i, j, k = 0, res = 1;
    >    for (i=0; i < 3; ++i)
    >      for (j=0; j < 3; ++j, ++k)
    >        res = res && (grid[row][k] != val) && (grid[k][col] != val) &&
    > (grid[ii+i][jj+j] != val);
    >    return res;
    >
    > }
    >
    > void solve(int pos)
    > {
    >    if (pos == 9*9) write_grid();
    >    else
    >    {
    >      int row, col, val;
    >      row = pos / 9;
    >      col = pos % 9;
    >      if (grid[row][col] != 0) solve(pos+1);
    >      else
    >      {
    >        for (val=1; val <= 9; ++val)
    >        {
    >          if (is_legal(row, col, val))
    >          {
    >            grid[row][col] = val;
    >            solve(pos+1);
    >          }
    >        }
    >        grid[row][col] = 0;
    >      }
    >    }
    >
    > }
    >
    > int main(void)
    > {
    >    read_grid(stdin);
    >    solve(0);
    >    return 0;
    >
    >
    >
    > }


    Compare your method with this:

    /* Program resolution of sudoku grids by backtracking,
    with propagation of the constraints and variable
    selection the most constrained (mrv: minimum remaining value).
    The file is read from stdin. Try for example with:

    53..7....
    6..195...
    .98....6.
    8...6...3
    4..8.3..1
    7...2...6
    .6....28.
    ...419..5
    ....8..79

    Bernard Helmstetter, 2006
    Translated to English by Dann Corbit
    */

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

    #define UNKNOWN 0

    int grid[81];
    int domain[81][10]; /* The list of possibilities */
    int domain_cuts[81]; /* domain cuts */
    int computer_nodes;

    /* Read the grid from standard input, using the characters '0'-'9' and
    '.' */
    void read_grid()
    {
    int k = 0;

    while (k < 81) {
    char c = getchar();
    if (c >= '1' && c <= '9')
    grid[k++] = c - '0';
    else if (c == '.')
    grid[k++] = UNKNOWN;
    else if (c == EOF) {
    fprintf(stderr, "Bad format reading grid\n");
    exit(1);
    }
    }
    }

    /* print the grid to standard output */
    void print_grid()
    {
    int c,
    l;

    for (l = 0; l < 9; l++) {
    for (c = 0; c < 9; c++) {
    int k = l * 9 + c;
    if (grid[k] == UNKNOWN)
    printf(".");
    else
    printf("%c", grid[k] + '0');
    }
    putchar('\n');
    }
    putchar('\n');
    }

    /* remove all the values of the domains that are incompatible for case
    'i' */
    void restrict_domain(int i)
    {
    int l = i / 9,
    c = i % 9;
    int lb = l / 3;
    int cb = c / 3;
    int l2,
    c2,
    lr2,
    cr2,
    i2;

    /* column constraints for case 'i' */
    for (l2 = 0; l2 < 9; l2++) {
    i2 = l2 * 9 + c;
    if (domain[i2][grid]) {
    domain[i2][grid] = 0;
    domain_cuts[i2]--;
    }
    }

    /* row constraints for case 'i' */
    for (c2 = 0; c2 < 9; c2++) {
    i2 = l * 9 + c2;
    if (domain[i2][grid]) {
    domain[i2][grid] = 0;
    domain_cuts[i2]--;
    }
    }

    /* verify the region containing case 'i' */
    for (lr2 = 0; lr2 < 3; lr2++)
    for (cr2 = 0; cr2 < 3; cr2++) {
    i2 = (lb * 3 + lr2) * 9 + (cb * 3 + cr2);
    if (domain[i2][grid]) {
    domain[i2][grid] = 0;
    domain_cuts[i2]--;
    }
    }
    }

    /* using the initial state, initialize the domain table */
    void init_domain()
    {
    int i,
    v;

    for (i = 0; i < 81; i++) {
    domain_cuts = 9;
    for (v = 1; v <= 9; v++)
    domain[v] = 1;
    }

    /* restrict the domain by backtracking */
    for (i = 0; i < 81; i++)
    if (grid != UNKNOWN)
    restrict_domain(i);
    }

    void backtrack()
    {
    int i,
    i_min = -1;
    int cuts_min = 10;
    int domain2[81][10];
    int domain_cuts2[81];

    /* look for a smaller domain */
    for (i = 0; i < 81; i++) {
    if (grid == UNKNOWN && domain_cuts < cuts_min) {
    i_min = i;
    cuts_min = domain_cuts;
    }
    }

    /* Are all UNKNOWN fields resolved? */
    if (i_min == -1) {
    print_grid(); /* solution found */
    return;
    }
    computer_nodes++;
    for (grid[i_min] = 1; grid[i_min] <= 9; grid[i_min]++) {
    if (domain[i_min][grid[i_min]] == 0)
    continue;
    /* Save the state between recursive calls */
    memcpy(domain2, domain, sizeof(domain));
    memcpy(domain_cuts2, domain_cuts, sizeof(domain_cuts));
    restrict_domain(i_min);
    backtrack();
    memcpy(domain, domain2, sizeof(domain));
    memcpy(domain_cuts, domain_cuts2, sizeof(domain_cuts));
    }
    grid[i_min] = UNKNOWN;
    }

    int main()
    {
    read_grid();
    print_grid();
    init_domain();
    backtrack(0);
    printf("%d nodes searched\n", computer_nodes);
    return 0;
    }
     
    user923005, Oct 16, 2008
    #6
  7. Richard<> writes:

    > "Default User" <> writes:
    >
    >> Trent Josephsen wrote:
    >>
    >>> Boon wrote:

    >>
    >>> > #include <stdio.h>
    >>> >
    >>> > static int grid[9][9];
    >>>
    >>> Generally you want to avoid global variables, as you probably know.

    >>
    >> I disagree. This is a perfect usage for file scope (NOT global) data
    >> constructs. I've been using that sort of thing for my game programming
    >> some lately. It's a sort of data encapsulation model.

    <snip>

    > Frankly I think that is nonsense.

    <snip>
    > And file scope IS global (as anyone without a rod up their arse knows
    > it) since anyone can declare an extern and then see it.


    No. No matter how rude you are, you can't alter the fact that, in C,
    scope and linkage are disconnected. The term "global" (usually)
    conflates them.

    Brian talks about encapsulation and non-global file scope data so I
    conclude he is talking about static objects declared at file scope
    which can not be seen using an "extern".

    Even if this not what he meant, file scope is /not/ global (rod or no
    rod).

    --
    Ben.
     
    Ben Bacarisse, Oct 16, 2008
    #7
  8. Boon

    Richard Guest

    Ben Bacarisse <> writes:

    > Richard<> writes:
    >
    >> "Default User" <> writes:
    >>
    >>> Trent Josephsen wrote:
    >>>
    >>>> Boon wrote:
    >>>
    >>>> > #include <stdio.h>
    >>>> >
    >>>> > static int grid[9][9];
    >>>>
    >>>> Generally you want to avoid global variables, as you probably know.
    >>>
    >>> I disagree. This is a perfect usage for file scope (NOT global) data
    >>> constructs. I've been using that sort of thing for my game programming
    >>> some lately. It's a sort of data encapsulation model.

    > <snip>
    >
    >> Frankly I think that is nonsense.

    > <snip>
    >> And file scope IS global (as anyone without a rod up their arse knows
    >> it) since anyone can declare an extern and then see it.

    >
    > No. No matter how rude you are, you can't alter the fact that, in C,
    > scope and linkage are disconnected. The term "global" (usually)
    > conflates them.


    No. Forget linkaqe. We do not discuss Linkage. A file variable is
    available globally to the program which is being compiled. You can play
    word games if you wish. There was no mention of static.

    >
    > Brian talks about encapsulation and non-global file scope data so I
    > conclude he is talking about static objects declared at file scope
    > which can not be seen using an "extern".


    You assume. But he did not mention static. I did. And there is no need
    for them to file scope either. This was my point.

    Without the mention of static then it can possibly be deduced that he
    was doing a Heathfield and suggesting no such thing as Globals in C.

    >
    > Even if this not what he meant, file scope is /not/ global (rod or no
    > rod).


    Where do YOU declare your globals Ben? In something that is NOT a
    file?

    What part of you can access via an extern is wrong? In the obvious and
    non clever understanding of what a global is?
     
    Richard, Oct 16, 2008
    #8
  9. Boon

    Guest

    Richard wrote:
    > "Default User" <> writes:
    >
    > > Trent Josephsen wrote:
    > >
    > >> Boon wrote:

    > >
    > >> > #include <stdio.h>
    > >> >
    > >> > static int grid[9][9];
    > >>
    > >> Generally you want to avoid global variables, as you probably know.

    > >
    > > I disagree. This is a perfect usage for file scope (NOT global) data
    > > constructs. I've been using that sort of thing for my game programming
    > > some lately. It's a sort of data encapsulation model.
    > >
    > >
    > >
    > >
    > > Brian

    >
    > Frankly I think that is nonsense.
    >
    > If efficiency was the issue he could simply malloc one bunch of result
    > containers or use in function statics to effectively hide things.
    >
    > And file scope IS global (as anyone without a rod up their arse knows
    >
    > it) since anyone can declare an extern and then see it.


    That statement implies that you're unfamiliar with the meaning of
    'static' when applied at file scope. Contrary to what you're
    suggesting, such declarations have internal linkage, not external
    linkage. As a result, declaring the same identifier with external
    linkage in a different translation unit will not make this definition
    visible in that translation unit. You need to understand the
    distinction between scope and linkage.

    This is not a pedantic quibble, since 'grid' was in fact declared with
    the keyword 'static'.
     
    , Oct 16, 2008
    #9
  10. Boon

    Richard Guest

    writes:

    > Richard wrote:
    >> "Default User" <> writes:
    >>
    >> > Trent Josephsen wrote:
    >> >
    >> >> Boon wrote:
    >> >
    >> >> > #include <stdio.h>
    >> >> >
    >> >> > static int grid[9][9];
    >> >>
    >> >> Generally you want to avoid global variables, as you probably know.
    >> >
    >> > I disagree. This is a perfect usage for file scope (NOT global) data
    >> > constructs. I've been using that sort of thing for my game programming
    >> > some lately. It's a sort of data encapsulation model.
    >> >
    >> >
    >> >
    >> >
    >> > Brian

    >>
    >> Frankly I think that is nonsense.
    >>
    >> If efficiency was the issue he could simply malloc one bunch of result
    >> containers or use in function statics to effectively hide things.
    >>
    >> And file scope IS global (as anyone without a rod up their arse knows
    >>
    >> it) since anyone can declare an extern and then see it.

    >
    > That statement implies that you're unfamiliar with the meaning of
    > 'static' when applied at file scope. Contrary to what you're


    No one mentioned static. I mentioned static.

    > suggesting, such declarations have internal linkage, not external
    > linkage. As a result, declaring the same identifier with external
    > linkage in a different translation unit will not make this definition
    > visible in that translation unit. You need to understand the
    > distinction between scope and linkage.


    I dont know where you got that impression of my meaning. I suppose its
    that word "declare" again. I should have posted an example.

    So you are telling me that "extern int c" in a header declares a new
    object? Wow. My C is rusty ....

    >
    > This is not a pedantic quibble, since 'grid' was in fact declared with
    > the keyword 'static'.


    My point is valid. He is as well to maintain internal statics "in
    function" or a malloc result set..

    Littering stuff at file scope is poor practice in most cases.
     
    Richard, Oct 16, 2008
    #10
  11. Boon

    Guest

    Richard wrote:
    > Ben Bacarisse <> writes:
    > > Richard<> writes:
    > >> "Default User" <> writes:
    > >>> Trent Josephsen wrote:
    > >>>> Boon wrote:

    ....

    You appear to have found the "static" keyword in the following
    declaration invisible:

    > >>>> > static int grid[9][9];
    > >>>>
    > >>>> Generally you want to avoid global variables, as you probably know.
    > >>>
    > >>> I disagree. This is a perfect usage for file scope (NOT global) data
    > >>> constructs. I've been using that sort of thing for my game programming
    > >>> some lately. It's a sort of data encapsulation model.

    > > <snip>
    > >
    > >> Frankly I think that is nonsense.

    > > <snip>
    > >> And file scope IS global (as anyone without a rod up their arse knows
    > >> it) since anyone can declare an extern and then see it.

    > >
    > > No. No matter how rude you are, you can't alter the fact that, in C,
    > > scope and linkage are disconnected. The term "global" (usually)
    > > conflates them.

    >
    > No. Forget linkaqe. We do not discuss Linkage. ...


    Who's "we", kemo-sabe? I discuss linkage when it's relevant, as it is
    to the question of whether or not something is global.

    > ... A file variable is
    > available globally to the program which is being compiled.


    Unless explicitly defined as static, in which case it has only
    internal linkage, and cannot be accessed by name from any translation
    unit of the program other than the one in which it was so defined.

    > ... You can play
    > word games if you wish. There was no mention of static.


    The declaration under discussion, which you yourself have quoted, says

    static int grid[9][9];

    That looks like a mention of "static" to me.

    > > Brian talks about encapsulation and non-global file scope data so I
    > > conclude he is talking about static objects declared at file scope
    > > which can not be seen using an "extern".

    >
    > You assume. But he did not mention static.


    The relevant use of the word "static" was the one written by Boon in
    the very first message of this discussion. Not by you, and not by
    Brian.


    > Without the mention of static then it can possibly be deduced that he
    > was doing a Heathfield and suggesting no such thing as Globals in C.


    Since Boon did mention static, you can drop that line of thought.

    > > Even if this not what he meant, file scope is /not/ global (rod or no
    > > rod).

    >
    > Where do YOU declare your globals Ben? In something that is NOT a
    > file?


    He's not saying that globals don't have file scope. He's saying that
    not all things declared with file scope are globals. Some things
    declared at file scope have internal linkage, and therefore cannot, by
    any reasonable definition of the term, be called globals. This doesn't
    have anything to do with Richard Heathfield's definition of global; I
    am in agreement with you that his definition is an unreasonably strict
    definition.

    > What part of you can access via an extern is wrong?


    The part where an extern declaration in one translation unit will NOT
    make visible an object (or function) declared 'static' at file scope
    in a different translation unit.
     
    , Oct 16, 2008
    #11
  12. Boon

    Guest

    Richard wrote:
    > writes:
    >
    > > Richard wrote:
    > >> "Default User" <> writes:
    > >>
    > >> > Trent Josephsen wrote:
    > >> >
    > >> >> Boon wrote:
    > >> >
    > >> >> > #include <stdio.h>


    The presence of the word "static" on the following line seems to
    somehow have repeatedly escaped your attention:

    > >> >> > static int grid[9][9];

    ....
    > >> it) since anyone can declare an extern and then see it.

    > >
    > > That statement implies that you're unfamiliar with the meaning of
    > > 'static' when applied at file scope. Contrary to what you're

    >
    > No one mentioned static. I mentioned static.


    I bed to differ. In the section that you yourself have quoted above,
    Boon definitely mentioned 'static', and did so long before you did.

    <nit-pick>A strict interpretation of your last two sentences leads to
    the deduction that you are "no one". I think you meant to say "no one
    else". </nit-pick>

    > > suggesting, such declarations have internal linkage, not external
    > > linkage. As a result, declaring the same identifier with external
    > > linkage in a different translation unit will not make this definition
    > > visible in that translation unit. You need to understand the
    > > distinction between scope and linkage.

    >
    > I dont know where you got that impression of my meaning. I suppose its
    > that word "declare" again. I should have posted an example.


    No, it's not your use of declare (unless you actually meant "define"
    in the following citation, in which case the sentence becomes
    irrelevant to the subject under discussion, since the relevant object
    was defined with 'static', not 'extern'). The problem is your use of
    extern in the following:

    > >> it) since anyone can declare an extern and then see it.


    That's true only of identifiers with external linkage, not identifiers
    with internal linkage; file scope alone is not sufficient to make that
    true.

    > So you are telling me that "extern int c" in a header declares a new
    > object? Wow. My C is rusty ....


    No, I'm telling you that 'static int c' declared in one translation
    unit and 'extern int c' declared in a different translation unit
    cannot both refer to the same object, not even if the static
    declaration occurs at file scope. The object referred to by the
    'extern' declaration must also be defined somewhere, not merely
    declared, but the 'static' declaration cannot provide that definition.
    If you were not aware of this fact, as seems to be the case, then your
    C is indeed rusty.

    > > This is not a pedantic quibble, since 'grid' was in fact declared with
    > > the keyword 'static'.

    >
    > My point is valid. He is as well to maintain internal statics "in
    > function" or a malloc result set..
    >
    > Littering stuff at file scope is poor practice in most cases.


    I would generally agree, for objects with external linkage. I think
    that file scope objects with internal linkage can be good practice in
    many cases. Your statements to the contrary notwithstanding, only
    functions in the same translation unit can see them, but all of those
    functions can see them, which can be a useful combination in some
    contexts. I've used such objects to coordinate the behavior of a call-
    back function with the behavior of another function; those were the
    only two functions which knew about the file-scope variable that
    shared the same translation unit with them; it was invisible to all
    the other translation units in the program.
     
    , Oct 17, 2008
    #12
  13. Boon

    Default User Guest

    Ben Bacarisse wrote:

    > Richard<> writes:
    >
    > > "Default User" <> writes:


    > >> I disagree. This is a perfect usage for file scope (NOT global)
    > >> data constructs. I've been using that sort of thing for my game
    > >> programming some lately. It's a sort of data encapsulation model.

    > <snip>
    >
    > > Frankly I think that is nonsense.

    > <snip>
    > > And file scope IS global (as anyone without a rod up their arse
    > > knows it) since anyone can declare an extern and then see it.

    >
    > No. No matter how rude you are, you can't alter the fact that, in C,
    > scope and linkage are disconnected. The term "global" (usually)
    > conflates them.


    Riley's a troll and an idiot, so no surprises there. And of course,
    I've had him killfiled for a long time. I'm not sure he believes it,
    but it's true.

    > Brian talks about encapsulation and non-global file scope data so I
    > conclude he is talking about static objects declared at file scope
    > which can not be seen using an "extern".


    Yeppers. I've been encapsulating some of the operations through the use
    of file-scope static data, static utility functions, and a small set of
    public interface functions. In some ways it's like OO programming writ
    large. In other ways it's very different.

    > Even if this not what he meant, file scope is not global (rod or no
    > rod).


    I think I didn't express my initial thoughts well enough if you're
    unsure. I can't draw any conclusions from Riley being confused.




    Brian
     
    Default User, Oct 17, 2008
    #13
  14. pete <> writes:

    > Ben Bacarisse wrote:
    >
    >> No matter how rude you are, you can't alter the fact that, in C,
    >> scope and linkage are disconnected.

    >
    > "Scope" is what "linkage" is all about.


    Yes, "disconnected" is too strong. Orthogonal? Too technical (and
    the technical means has to be bent for it to fit). Independent?
    Probably also too strong.

    The trouble with the word "global" is that it conflates two ideas that
    need to be taken separately to understand what is happening in C
    programs.

    --
    Ben.
     
    Ben Bacarisse, Oct 17, 2008
    #14
  15. "Default User" <> writes:

    > Ben Bacarisse wrote:

    <snip>
    >> Brian talks about encapsulation and non-global file scope data so I
    >> conclude he is talking about static objects declared at file scope
    >> which can not be seen using an "extern".

    >
    > Yeppers. I've been encapsulating some of the operations through the use
    > of file-scope static data, static utility functions, and a small set of
    > public interface functions. In some ways it's like OO programming writ
    > large. In other ways it's very different.
    >
    >> Even if this not what he meant, file scope is not global (rod or no
    >> rod).

    >
    > I think I didn't express my initial thoughts well enough if you're
    > unsure.


    No, I was clear about what you meant. I simply wanted to cover myself
    to cut down on the number of posts exchanged since I knew Just Plain
    Richard would accuse me of making unwarranted assumptions.

    --
    Ben.
     
    Ben Bacarisse, Oct 17, 2008
    #15
  16. Boon

    Boon Guest

    Hello Dann,

    user923005 wrote:

    > Boon wrote:
    >
    >> I've been toying with a simple sudoku[1] solver. I meant for the code to
    >> be short and easy to understand. I figured "brute force is simple" --
    >> who needs finesse, when you've got muscle, right? :)
    >>
    >> [1]http://en.wikipedia.org/wiki/Sudoku
    >>
    >> Thus, the strategy is to test every legal "move" and to backtrack when
    >> stuck. A recursive function seemed appropriate. I'd like to hear
    >> comments and suggestions regarding the implementation.
    >>
    >> [snip my implementation]

    >
    > Compare your method with this:
    >
    > /* Program resolution of sudoku grids by backtracking,
    > with propagation of the constraints and variable
    > selection the most constrained (mrv: minimum remaining value).
    > The file is read from stdin. Try for example with:
    >
    > 53..7....
    > 6..195...
    > .98....6.
    > 8...6...3
    > 4..8.3..1
    > 7...2...6
    > .6....28.
    > ...419..5
    > ....8..79
    >
    > Bernard Helmstetter, 2006
    > Translated to English by Dann Corbit
    > */
    >
    > [snip Bernard's implementation]


    Thanks Dann. In my opinion, Bernard's method is more complex than mine,
    but it is very likely faster. Were there specific differences you wanted
    to highlight ?

    Regards.
     
    Boon, Oct 20, 2008
    #16
  17. On 16 Oct, 22:11, Richard<> wrote:
    > Ben Bacarisse <> writes:
    > > Richard<> writes:
    > >> "Default User" <> writes:
    > >>> Trent Josephsen wrote:
    > >>>> Boon wrote:


    > >>>> > #include <stdio.h>

    >
    > >>>> > static int grid[9][9];

    >
    > >>>> Generally you want to avoid global variables, as you probably know.

    >
    > >>> I disagree. This is a perfect usage for file scope (NOT global) data
    > >>> constructs. I've been using that sort of thing for my game programming
    > >>> some lately. It's a sort of data encapsulation model.

    >
    > >> Frankly I think that is nonsense.

    >
    > >> And file scope IS global <snip unnecessary rudeness> since anyone can
    > >> declare an extern and then see it.

    >
    > > No.  No matter how rude you are, you can't alter the fact that, in C,
    > > scope and linkage are disconnected.  The term "global" (usually)
    > > conflates them.


    ah, Richard <whoever> has been at Troll Pills again!


    > No. Forget linkaqe. We do not discuss Linkage.


    yes we do!

    > A file variable is
    > available globally to the program which is being compiled. You can play
    > word games if you wish. There was no mention of static.


    it is available at file scope. It could be said to be available
    to the Tranaslation Unit but it ain't available to the program!

    The trouble with the word "global" is it needs some context.
    I used to use it situations like this

    char *base_addr;

    /* lots of code */

    char read_dma_setting (void)
    {return *(base_addr + DMA_SETTING_OFFSET);}

    /* more code */
    base_addr = 0x80001234;
    rds = read_dma_setting();

    [I *really* don't write code like that anymore!]

    I'd describe base_addr as a "global parameter" of
    read_dma_setting(). The term "global" would float around as well.
    I found it ambiguous and stopped using the term. Some people
    used to global to mean visible throughout the program.
    Some just meant file visible. Its a confusing term.
    Nowadays I use it as a pejorative term meaning "having too
    much scope". "This program would be more robust if it used
    less globals".


    > > Brian talks about encapsulation and non-global file scope data so I
    > > conclude he is talking about static objects declared at file scope
    > > which can not be seen using an "extern".

    >
    > You assume.


    pretty reasonable assumption. Note "file scope"

    > But he did not mention static.


    static int grid[9][9];

    (I'm not sure if that was what "Brian" posted as he's been snipped


    > I did. And there is no need
    > for them to file scope either. This was my point.
    >
    > Without the mention of static then it can possibly be deduced that he
    > was doing a Heathfield and suggesting no such thing as Globals in C.


    There *is* no such thing as a global in C. See the standard.


    > > Even if this not what he meant, file scope is /not/ global


    why not if you must use the word it's a reasonable usage.
    If you mean "global" to ba an alias for "external linkage"
    why not use the term?

    <snip rudeness>

    <snip stuff>


    --
    Nick Keighley
     
    Nick Keighley, Oct 20, 2008
    #17
  18. On 16 Oct, 22:21, Richard<> wrote:

    > Littering stuff at file scope is poor practice in most cases


    depends what "littering" means. I submit most well written
    non-trivial C programs have some file scope data.

    Good way to start another argument anyway...

    --
    Nick Keighley
     
    Nick Keighley, Oct 20, 2008
    #18
  19. Boon

    James Kuyper Guest

    Nick Keighley wrote:
    ....
    > There *is* no such thing as a global in C. See the standard.


    The standard uses the term "global variables" only once (F8.1p1) and
    does not define the term. However, that one use involves saying that
    "The flags and modes in the floating-point environment may be regarded
    as global variables...", which seems pretty inconsistent with the idea
    that there is no such thing in C. Unlike several of the other Annexes,
    Annex F is marked as "normative".

    Since the C standard doesn't define what the term means, we have to fall
    back on, in order of increasing relevance: ordinary English usage,
    common usage in IT contexts, and ISO/IEC 2382−1 (a standard far too
    expensive for me to have a copy of). I believe that it is both common
    usage and quite reasonable in C contexts to use the term "global" to
    refer to identifiers with external linkage.

    I've heard arguments that such identifiers are not truly "global",
    because they can be hidden by declarations of the same identifier with
    internal linkage. While I can appreciate the point being made, I
    consider it insufficiently convincing to justify breaking with common
    usage. In ordinary English usage, companies (for instance) are said to
    be global if they have a presence almost everywhere around the globe,
    even if there are a few places where they have no presence.

    ....
    > If you mean "global" to ba an alias for "external linkage"
    > why not use the term?


    Because the term "global" is in common usage with this meaning, and is a
    lot easer to say than "with external linkage".
     
    James Kuyper, Oct 20, 2008
    #19
  20. Boon

    Guest

    Richard wrote:
    > writes:
    > > Richard wrote:
    > >> "Default User" <> writes:
    > >> > Trent Josephsen wrote:
    > >> >> Boon wrote:
    > >> >> > #include <stdio.h>
    > >> >> >
    > >> >> > static int grid[9][9];

    ....
    > >> And file scope IS global (as anyone without a rod up their arse knows
    > >>
    > >> it) since anyone can declare an extern and then see it.

    ....
    > > suggesting, such declarations have internal linkage, not external
    > > linkage. As a result, declaring the same identifier with external
    > > linkage in a different translation unit will not make this definition
    > > visible in that translation unit. You need to understand the
    > > distinction between scope and linkage.

    >
    > I dont know where you got that impression of my meaning. I suppose its
    > that word "declare" again. I should have posted an example.


    Perhaps you should. I don't know how to make a file scope identifier
    with internal linkage (such as the array 'grid' defined above) visible
    from another translation unit by "declar[ing] an extern", unless the
    identifier with external linkage refers to something different from
    what the identifier with internal linkage refers to. If you know how
    to do this, could you give us an example?
     
    , Oct 20, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bas

    Brute force sudoku cracker

    Bas, Sep 16, 2005, in forum: Python
    Replies:
    21
    Views:
    3,280
    Dennis Lee Bieber
    Sep 23, 2005
  2. ago
    Replies:
    11
    Views:
    713
    Anton Vredegoor
    Jan 20, 2006
  3. Replies:
    0
    Views:
    329
  4. Derek  Marshall

    sudoku solver in Python ...

    Derek Marshall, Jan 24, 2008, in forum: Python
    Replies:
    6
    Views:
    504
    Boris Borcic
    Jan 25, 2008
  5. SuDoku-X Solver

    , Aug 17, 2005, in forum: Ruby
    Replies:
    2
    Views:
    178
    Mohit Muthanna
    Aug 18, 2005
Loading...

Share This Page