Thread: Hodor Wears Shoes

  1. #1
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787

    Hodor Wears Shoes

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int tielaces(void)
    {
        return rand() & 0;
    }
    
    int usevelcro(void)
    {
        return rand() | 1;
    }
    
    int main(void)
    {
        srand(time(NULL));
        
        if (tielaces())
            puts("Hodor tied laces. Hodor!");
        else if (usevelcro())
            puts("Hodor secured shoes! Hodor, Hodor, Hodor! (stomps feet)");
        else 
            puts("Hodor failed. Hodor.");
        
        return 0;
    }

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    << oh dear lord! >>
    Last edited by Adak; 11-22-2013 at 07:09 PM.

  3. #3
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <limits.h>
    
    #define KNUTH_MULTIPLIER    1812433253UL
    #define KNUTH_SHIFT         30
    
    #define MT_UTNLEN           624
    #define MT_MAGICN           397
    #define MT_MATRIX           0x9908b0dfUL
    
    #define MT_SHIFTA           11
    #define MT_SHIFTB           7
    #define MT_SHIFTC           15
    #define MT_SHIFTD           18
    
    #define MT_MAGICMASKA       0x9d2c5680UL
    #define MT_MAGICMASKB       0xefc60000UL
    
    #define MT_BIT31            0x80000000UL
    #define MT_BITS0TO30        0x7FFFFFFFUL
    #define MT_MASK32           0xFFFFFFFFUL
    
    #if ULONG_MAX >> 32
    #   define MASKRESULT(d,s) ( (d) = (s) & MT_MASK32 )
    #else
    #   define MASKRESULT(d,s) (void)(0)
    #endif
    
    #define RAND_MT_MAX 0xffffffff
    
    struct mt {
        unsigned long   utn[MT_UTNLEN];
        int             idx;
    };
    
    /* "Handle" for Mersenne Twister object */
    typedef struct mt RAND_MT;
    
    inline static void mt_gen_(struct mt *mt);
    
    inline static unsigned long 
    knuth_prng(unsigned long pn, unsigned long n)
    {
        unsigned nrn = KNUTH_MULTIPLIER * (pn ^ (pn >> KNUTH_SHIFT)) + n;
        MASKRESULT(nrn, nrn);
        return nrn;
    }
    
    inline static void 
    mt_init_(struct mt *mt, unsigned long seed)
    {
        int i;
        unsigned long *utn = mt->utn;
        
        utn[0] = seed & MT_MASK32;
        for (i = 1; i < MT_UTNLEN; i++)
            utn[i] = knuth_prng(utn[i-1], i);
        
        /* Set mt->idx to i (MT_UTNLEN) so that the first call to mt_rand_()
         * triggers a call to mt_gen_()
         */
        mt->idx = i;
    }
    
    inline static unsigned long
    mt_combinebits_(unsigned long a, unsigned long b)
    {
        return (a & MT_BIT31) | (b & MT_BITS0TO30);
    }
    
    inline static unsigned long
    mt_matrixmultiply_(unsigned long a, unsigned long b)
    {
        static unsigned long magic[2] = {0UL, MT_MATRIX};
        return a ^ (b >> 1) ^ magic[b & 0x01];
    }
    
    inline static void 
    mt_gen_(struct mt *mt)
    {
        int i;
        unsigned long *utn = mt->utn, y;    
               
        for (i = 0; i < MT_UTNLEN - MT_MAGICN; i++) {
            y = mt_combinebits_(utn[i], utn[i + 1]);
            utn[i] = mt_matrixmultiply_(utn[i + MT_MAGICN], y);
        }
        for (; i < MT_UTNLEN - 1; i++) {
            y = mt_combinebits_(utn[i], utn[i + 1]);
            utn[i] = mt_matrixmultiply_(utn[i + MT_MAGICN - MT_UTNLEN], y);
        }
        y = mt_combinebits_(utn[i], utn[0]);
        utn[i] = mt_matrixmultiply_(utn[MT_MAGICN - 1], y);
                
        mt->idx = 0;
    }
    
    inline static unsigned long
    mt_rand_(struct mt *mt)
    {    
        unsigned long y;
        
        if (mt->idx >= MT_UTNLEN)
            mt_gen_(mt);
        
        y = mt->utn[mt->idx++];
        y ^= (y >> MT_SHIFTA);
        y ^= (y << MT_SHIFTB) & MT_MAGICMASKA;
        y ^= (y << MT_SHIFTC) & MT_MAGICMASKB;
        y ^= (y >> MT_SHIFTD);
        
        return y;
    }
    
    RAND_MT *
    mtrand_new(unsigned long seed)
    {
        RAND_MT *mt;
        if ((mt = malloc(sizeof *mt)) != NULL)
            mt_init_(mt, seed);
        return mt;
    }
    
    void 
    mtrand_dispose(RAND_MT *mt)
    {
        free(mt);
    }
    
    unsigned long
    mtrand_get(RAND_MT *mt)
    {
        return mt_rand_(mt);
    }
    
    static RAND_MT *rng;
    
    int 
    tielaces(void)
    {
        return mtrand_get(rng) & 0;
    }
     
    int 
    usevelcro(void)
    {
        return mtrand_get(rng) | 1;
    }
    
    
    int main(void)
    {
        if((rng = mtrand_new(time(NULL)))==NULL) {
            fputs("Could not initialise RNG. Aborting", stderr);
            return 1;
        }
        
        if (tielaces())
            puts("Hodor tied laces. Hodor!");
        else if (usevelcro())
            puts("Hodor secured shoes! Hodor, Hodor, Hodor! (stomps feet)");
        else
            puts("Hodor failed. Hodor.");
        
        mtrand_dispose(rng);
        
        return 0;
    }
    Last edited by Hodor; 11-22-2013 at 07:38 PM. Reason: Removed accidental header inclusion

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    And your question is...?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by iMalc View Post
    And your question is...?
    I'm not sure I have one but I'll try and think of one.

    I only just noticed that all the forums are basically for questions; that's a bit disappointing. Where would general C discussion or posts go? (My question)

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Another problem is that some really good answers get posted, and then naturally pushed down and off the first few pages fairly quickly. After that, they may never be found again.

    It would be great to keep the really good one's, around.

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Alright if there isn't any other specific question, then perhaps I'll just make a few comments.

    tielaces can only ever return zero, which appears to be a mistake.
    usevelcro on the other hand can never return zero, which also appears to be a mistake.
    What is your understanding on how bitwise operators work?

    Both inline and static are a bit OTT in this program, as it appears to be just a single source file.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Is Hodor a pokemon?

  9. #9
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by iMalc View Post
    Alright if there isn't any other specific question, then perhaps I'll just make a few comments.

    tielaces can only ever return zero, which appears to be a mistake.
    usevelcro on the other hand can never return zero, which also appears to be a mistake.
    What is your understanding on how bitwise operators work?

    Both inline and static are a bit OTT in this program, as it appears to be just a single source file.
    Thanks for the feedback, iMalc. The reason for those static functions is that I actually wrote the Mersenne twister part of the program as two files: whatever.c and whatever.h. I only wanted 3 functions (the last 3) available for programs hence why the rest are static. The only other part of the implementation is the struct for the "handles". Normally I don't typedef structs but in this case I could honestly seen nothing in the struct that could be remotely useful for anything except the implementation, therefore I kept the struct in the .c file and the .h file only has
    Code:
    typedef struct mt RAND_MT;
    prototypes for the three "public" functions, and RAND_MT_MAX.

    My understanding of bitwise operators is sound. The shoelace functions are in response to a comment made in another thread by Adak that I couldn't resist responding to; don't take them too seriously.

    I do have a question. Looking at my notes that accompany the original files I can see that I originally used uint32_t for the functions etc. and changed it to unsigned long. Is there is specific advantage or other reason for using on over the other?
    Last edited by Hodor; 11-23-2013 at 01:11 AM.

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    uint32_t is guaranteed to be 32 bits. From this information you can compute its range. On the other hand, stdint.h itself is C99, and that's where uint32_t comes from, and you can't really know what unsigned long supports for a range. The standard only has rules for requirements. Platforms are free to meet and exceed that requirement, as long as doing so doesn't exceed the environmental limits (which are themselves another set of rules).

    tl;dr: uint32_t is specific and generally that is a good thing.

  11. #11
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by whiteflags View Post
    tl;dr: uint32_t is specific and generally that is a good thing.
    Thanks. I've used unsigned long because by my understanding it must be at least 32 bits (according to section 5.2.4.2.1 of C99). I don't know if this is the same as the minimum value of ULONG_MAX in C89 because I don't have a copy of that standard. It makes no difference, though, if unsigned long is longer than 32-bits except that the upper bits must be masked out. I wrote the crazy macro at the top to decide whether or not the masking was needed. In that case I guess that using uint32_t would have avoided that problem with the only advantage that I know for certain the size (in bits) beforehand. It has the disadvantage of requiring uint32_t and thus is incompatible with C89, on the other hand I've used inline so I guess what I really need to do is decide if I'm aiming for c89 or c99 "compatibility".

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by iMalc View Post
    tielaces can only ever return zero, which appears to be a mistake.
    usevelcro on the other hand can never return zero, which also appears to be a mistake.
    Presumably these two observations mean that Hodor cannot tie shoelaces.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I only just noticed that all the forums are basically for questions; that's a bit disappointing. Where would general C discussion or posts go? (My question)
    This is actually a rather novel request to me. If you want to talk about code, that's fine. Actually talk about it though. A code dump is like regular dumps.

  14. #14
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Code:
    #include <stdio.h>
    
    int choose(void)
    {
       return rand() % 3;
    }
    int main(void)
    {
        int choice;
        
        srand(time(NULL));
        printf("Hehehee. *like*\n");
        printf("Oh noo, I just liked an in-joke. What do I do?\n");
        
        choice = choose();
        
        switch (choice)
        {
        case 0: 
            printf("HodorStalker! Go prowling over the boards and try to get in on an in joke.\n");
            break;
        case 1:
            printf("HodorBasher! Use unwanted shoelaces to create a circle of devastation.\n");
            break;    
        case 2: 
            printf("HodorDump! Dump nonsense in this quite unusual thread.\n");        
            break;
        }     
    }
    I ran it and got HodorBasher! Use unwanted shoelaces to create a circle of devastation..

    Anyway. To try to say something vaguely useful. I would have thought amusing threads like this might go in the general discussion board. Occasionally there are C discussions rather than questions, but this is pretty new. I was wondering what on earth your question could be. Trying to write a shoe designer in C and failing miserably perhaps.

    Hasty edit to correct the fact that I mispelled "Hodor" every single time. Heh.

  15. #15
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by whiteflags View Post
    This is actually a rather novel request to me. If you want to talk about code, that's fine. Actually talk about it though. A code dump is like regular dumps.
    In hindsight I went about the thread the wrong way. Initially it was a response to another thread, and I posted it merely to see what the other person would do (they said they'd do something the day they saw a thread where Hodor could tie his shoes). Anyway, after a while the little jape of mine began to unsettle me mainly because the code did nothing useful (post #1) and it's only purpose was a joke that a maximum of maybe one or two people might "get" even if it wasn't funny. So I decided to add something that was at least useful to the code whilst keeping the rather obscure jest. So, I added the Mersenne twister code I wrote last week to generate the random numbers (even though I don't seriously use those random numbers).

    Initially I implemented the algorithm as described on Wikipedia. Now it's not that I don't trust Wikipedia but things had to be tested! So I got the source code from an experimental OS and ran their algorithm and mine and compared output. Output didn't match That was fine, I figured I had a bug and spent over an hour trying to work out what the @$*@* was wrong. Eventually I tried looking for the primary source again. The main reference on the Wikipedia page leads to a paywalled site and I'd completely overlooked the external links section at the bottom of the Wikipedia page. Oops. So I then went to the Mersenne Twister home page hoping to find something that I was overlooking. Comparing the output of the "reference implementation" available on that page with the output from my source and the other source code I had first used as a comparison both output non-matching numbers. So a lazy afternoon spent implementing something to wile away the time ended up finding an implementation bug (well two if you count mine) -- the reference implementation trumps all others -- and I learned something interesting.

    -- Hodor

    Edit: I really tried to think of something more interesting for the initial (post #1) "shoe trying program" but I couldn't! Oh well, maybe something will come to be in the next few days that would have solved this knotty dilemma.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Hodor Can Multiply
    By Hodor in forum C Programming
    Replies: 16
    Last Post: 11-22-2013, 04:53 AM
  2. Hodor Can Divide
    By Hodor in forum C Programming
    Replies: 1
    Last Post: 11-22-2013, 04:41 AM
  3. How do you tie your shoes
    By MethodMan in forum A Brief History of Cprogramming.com
    Replies: 23
    Last Post: 08-11-2002, 07:13 PM