Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. Friday's Coding Challenge

Friday's Coding Challenge

Scheduled Pinned Locked Moved The Lounge
c++architectureperformancehelplounge
76 Posts 35 Posters 6 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y YvesDaoust

    Slightly modified Straight Selection Sort will do the trick (moves n lowest elements first):

    for (int i= 0; i < n; i++)
    {
    int k = i;
    for (int j= i; j < m; j++)
    {
    if (a[k] > a[j])
    {
    k = j;
    }
    }

    int swap= a\[i\]; a\[i\]= a\[k\]; a\[k\]= swap;
    

    }

    IMHO, allowing function calls makes the challenge nonsensical, as the solutions reduces to S(a, m, n), where S is the function that does just that.

    T Offline
    T Offline
    Trajan McGill
    wrote on last edited by
    #65

    Ahh, shoot, you're right. The requirements didn't specify a non-destructive algorithm. Your method, turned into an actual function, with a few optimizations and a bit of non-essential character elimination, reduces to:

    void g(int*a,int m,int n){int i=0,j,k,t;for(;ia[j])k=j;}

    which beats mine by 50 characters (49 if I chop out the one removable whitespace character I missed in my solution). If we modify it further to toss out the array notation and instead do horrible things with pointers, we can even save 6 more:

    void g(int*a,int m,int n){int*i=a,*j,*k,t;for(;i*j)k=j;}

    Y 2 Replies Last reply
    0
    • C Chris Maunder

      What's the smallest code you can come up with to find the n smallest numbers in a random sample of m numbers where n < m. Any language, speed is not an issue.

      cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP

      B Offline
      B Offline
      Bob Beechey
      wrote on last edited by
      #66

      If our list is the_list in Python we have new_list = sorted(the_list)[:n]

      1 Reply Last reply
      0
      • P PIEBALDconsult

        SELECT TOP n FROM Sample ORDER BY Value Edit: How should we handle duplicates?

        K Offline
        K Offline
        KP Lee
        wrote on last edited by
        #67

        That won't work in sql. :) (n isn't a number and value isn't selected)

        1 Reply Last reply
        0
        • T Trajan McGill

          Ahh, shoot, you're right. The requirements didn't specify a non-destructive algorithm. Your method, turned into an actual function, with a few optimizations and a bit of non-essential character elimination, reduces to:

          void g(int*a,int m,int n){int i=0,j,k,t;for(;ia[j])k=j;}

          which beats mine by 50 characters (49 if I chop out the one removable whitespace character I missed in my solution). If we modify it further to toss out the array notation and instead do horrible things with pointers, we can even save 6 more:

          void g(int*a,int m,int n){int*i=a,*j,*k,t;for(;i*j)k=j;}

          Y Offline
          Y Offline
          YvesDaoust
          wrote on last edited by
          #68

          And as said in my next post (have a look into the future), passing argument n is unessential, use m instead and spare 6 characters.

          T 1 Reply Last reply
          0
          • T Trajan McGill

            Ahh, shoot, you're right. The requirements didn't specify a non-destructive algorithm. Your method, turned into an actual function, with a few optimizations and a bit of non-essential character elimination, reduces to:

            void g(int*a,int m,int n){int i=0,j,k,t;for(;ia[j])k=j;}

            which beats mine by 50 characters (49 if I chop out the one removable whitespace character I missed in my solution). If we modify it further to toss out the array notation and instead do horrible things with pointers, we can even save 6 more:

            void g(int*a,int m,int n){int*i=a,*j,*k,t;for(;i*j)k=j;}

            Y Offline
            Y Offline
            YvesDaoust
            wrote on last edited by
            #69

            You can also get rid of variable i by working backwards, and benefit from a little of C's syntaxic sugar:

            void g(int a[], int m)
            {
            while (m)
            {
            int k= --m, j= m;
            while (j)
            k= a[k] < a[--j] ? k : j;

            	int s= a\[m\]; a\[m\]= a\[k\]; a\[k\]= s;
            }
            

            }

            (This code guaranteed unchecked for correctness :-)) Applying your transforms should give something shorter than ever.

            1 Reply Last reply
            0
            • C Chris Maunder

              What's the smallest code you can come up with to find the n smallest numbers in a random sample of m numbers where n < m. Any language, speed is not an issue.

              cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP

              Y Offline
              Y Offline
              YvesDaoust
              wrote on last edited by
              #70

              This is a straight selection sort, processing back to front and doing immediate swaps to avoid index bookeeping.

              void g(int a[], int m)
              {
              for (int s, p; p= --m;)
              while (p--)
              if (s= a[m], a[p] > s)
              a[m]= a[p], a[p]= s;
              }

              or, said shortly,

              void g(int*a,int m){for(int s,p;p=--m;)while(p--)if(s=a[m],a[p]>s)a[m]=a[p],a[p]=s;}

              The requested solution lies in a[0..n-1]. I guess it will be hard to improve on this straight selection approach, given that - two nested loops are required, - two decreasing indexes are required (m and p), - a swap variable is required (s), - a key comparison is required, - three assignments are required for the swaps, wherever they take place.

              T 1 Reply Last reply
              0
              • Y YvesDaoust

                And as said in my next post (have a look into the future), passing argument n is unessential, use m instead and spare 6 characters.

                T Offline
                T Offline
                Trajan McGill
                wrote on last edited by
                #71

                Good point, once you're doing a sort like this, you might as well just sort the whole array.

                Y 2 Replies Last reply
                0
                • T Trajan McGill

                  Good point, once you're doing a sort like this, you might as well just sort the whole array.

                  Y Offline
                  Y Offline
                  YvesDaoust
                  wrote on last edited by
                  #72

                  Yep, they say running time is for free...

                  1 Reply Last reply
                  0
                  • T Trajan McGill

                    Good point, once you're doing a sort like this, you might as well just sort the whole array.

                    Y Offline
                    Y Offline
                    YvesDaoust
                    wrote on last edited by
                    #73

                    And by the way, I have explored an approach where the high values in the array are allowed to be destroyed. Just passing parameter n spoils this effort !

                    1 Reply Last reply
                    0
                    • Y YvesDaoust

                      This is a straight selection sort, processing back to front and doing immediate swaps to avoid index bookeeping.

                      void g(int a[], int m)
                      {
                      for (int s, p; p= --m;)
                      while (p--)
                      if (s= a[m], a[p] > s)
                      a[m]= a[p], a[p]= s;
                      }

                      or, said shortly,

                      void g(int*a,int m){for(int s,p;p=--m;)while(p--)if(s=a[m],a[p]>s)a[m]=a[p],a[p]=s;}

                      The requested solution lies in a[0..n-1]. I guess it will be hard to improve on this straight selection approach, given that - two nested loops are required, - two decreasing indexes are required (m and p), - a swap variable is required (s), - a key comparison is required, - three assignments are required for the swaps, wherever they take place.

                      T Offline
                      T Offline
                      Trajan McGill
                      wrote on last edited by
                      #74

                      Actually, we can do away with one of the loops if we make use of some evaluation short circuiting trickery to make one loop act like two. Thus this:

                      void g(int*a,int m){for(int s,p;p=--m;)while(p--)if(s=a[m],a[p]>s)a[m]=a[p],a[p]=s;}

                      becomes this:

                      void g(int*a,int m){for(int s,p=0;p--||(p=--m);)if(s=a[m],a[p]>s)a[m]=a[p],a[p]=s;}

                      which saves us one whole character. :) It might be possible to figure out a way to cut off a couple more, I'm not sure. I've considered, but not had enough time to exhaust, possibilities like going forward vs. backward on either one or both of the iterators, using a pointer rather than an index into the array, whether sorting in reverse order (putting the smallest elements at the end of the array rather than the beginning) might help, and the possibility of somehow using the array itself for swapping to eliminate a variable, but probably most of these are going to add code rather than reduce it. There's also the possibility of a recursive solution, but I haven't really tried that at all. I have to go do some real work, unfortunately, but this C solution is getting surprisingly close in length to some of the solutions using languages with handy built-in functions to do this sort of thing.

                      Y 1 Reply Last reply
                      0
                      • T Trajan McGill

                        Actually, we can do away with one of the loops if we make use of some evaluation short circuiting trickery to make one loop act like two. Thus this:

                        void g(int*a,int m){for(int s,p;p=--m;)while(p--)if(s=a[m],a[p]>s)a[m]=a[p],a[p]=s;}

                        becomes this:

                        void g(int*a,int m){for(int s,p=0;p--||(p=--m);)if(s=a[m],a[p]>s)a[m]=a[p],a[p]=s;}

                        which saves us one whole character. :) It might be possible to figure out a way to cut off a couple more, I'm not sure. I've considered, but not had enough time to exhaust, possibilities like going forward vs. backward on either one or both of the iterators, using a pointer rather than an index into the array, whether sorting in reverse order (putting the smallest elements at the end of the array rather than the beginning) might help, and the possibility of somehow using the array itself for swapping to eliminate a variable, but probably most of these are going to add code rather than reduce it. There's also the possibility of a recursive solution, but I haven't really tried that at all. I have to go do some real work, unfortunately, but this C solution is getting surprisingly close in length to some of the solutions using languages with handy built-in functions to do this sort of thing.

                        Y Offline
                        Y Offline
                        YvesDaoust
                        wrote on last edited by
                        #75

                        Nice trick !

                        1 Reply Last reply
                        0
                        • C Chris Maunder

                          What's the smallest code you can come up with to find the n smallest numbers in a random sample of m numbers where n < m. Any language, speed is not an issue.

                          cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP

                          M Offline
                          M Offline
                          Member 8085210
                          wrote on last edited by
                          #76

                          Let x be such a sample. Then x[rank(x)<=n] is such a subsample, in R. If there are elements in the sample that are repeated and you want the first n different numbers, it is a bit more complicated, since you have to check first that there are at least n different elements in your sample, using ux<-unique(x), for instance.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups