Sorting algorithms/Bead sort: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Fortran}}: note about large integers)
(→‎{{header|J}}: ++ octave)
Line 234: Line 234:
bead bead 5 3 1 7 4 1 1
bead bead 5 3 1 7 4 1 1
7 5 4 3 1 1 1</lang>
7 5 4 3 1 1 1</lang>

=={{header|Octave}}==
{{trans|Fortran}}
<lang octave>function sorted = beadsort(a)
sorted = a;
m = max(a);
if ( any(a < 0) )
error("can't sort");
endif
t = zeros(m, m);
for i = 1:numel(a)
t(i, 1:a(i)) = 1;
endfor
for i = 1:m
s = sum(t(:, i));
t(:, i) = 0;
t(1:s, i) = 1;
endfor
for i = 1:numel(a)
sorted(i) = sum(t(i, :));
endfor
endfunction

beadsort([5, 7, 1, 3, 1, 1, 20])</lang>


=={{header|Tcl}}==
=={{header|Tcl}}==

Revision as of 14:54, 28 August 2010

Task
Sorting algorithms/Bead sort
You are encouraged to solve this task according to the task description, using any language you may know.

In this task, the goal is to sort an array of positive integers using the Bead Sort Algorithm.

Algorithm has O(S), where S is the sum of the integers in the input set: Each bead is moved individually. This is the case when bead sort is implemented without a mechanism to assist in finding empty spaces below the beads, such as in software implementations.

C

A rather straightforward implementation; since we do not use dynamic matrix, we have to know the maximum value in the array in advance. Using no sparse matrix means the matrix needs MAX*MAX times the size of an integer bytes to be stored.

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <stdbool.h>
  3. include <string.h>

int *bead_sort(int *a, size_t len) {

 size_t i, j, k;
 bool fallen;
 int *t, *r = NULL;
 int max = a[0];
 for(i = 1; i < len; i++) 
 {
   if ( a[i] < 0 ) return NULL;  // we can't sort nums < 0
   if ( max < a[i] ) max = a[i];
 }
 
 t = malloc(max*max*sizeof(int));
 if ( t == NULL ) return NULL;
 memset(t, 0, max*max*sizeof(int));
 r = malloc(len*sizeof(int));
 memset(r, 0, len*sizeof(int));
 if (r != NULL) 
 {
   // "split" numbers into "beads" (units)
   for(i = 0; i < len; i++)
   {
     for(j = 0; j < a[i]; j++) t[i*max + j]++;
   }
   // make them fall down
   do
   {
     fallen = false;
     for(i = 0; i < max-1; i++)
     {

for(j = 0; j < max; j++) { if ( t[i*max + j] == 1 && t[(i+1)*max + j] == 0 ) { fallen = true; t[i*max + j] = 0; t[(i+1)*max + j] = 1; } }

     }
   } while(fallen);
  1. if defined(SHOW_BEADS)
   for(i = 0; i < max; i++)
   {
     for(j = 0; j < max; j++)
     {

printf("%d ", t[i*max + j]);

     }
     printf("\n");
   }
  1. endif
   // count beads
   k = 0;
   for(i = 0; i < max; i++)
   {
     if ( t[(max - i - 1)*max + 0] == 0 ) break;
     for(j = 0; j < max; j++)
     {

int v = t[(max - i - 1)*max + j]; if ( v == 0 ) break; r[k] += v;

     }
     k++;
   }
   
 }
 free(t);
 return r;

}

int main() {

 int values[] = {5, 3, 1, 7, 4, 1, 1, 20};
 size_t i, len = sizeof(values)/sizeof(int);
 int *r = bead_sort(values, len);
 if ( r == NULL ) return EXIT_FAILURE;
 for(i = 0; i < len; i++)
 {
   printf("%d ", r[i]);
 }
 putchar('\n');
 free(r);
 return EXIT_SUCCESS;

}</lang>

C++

<lang cpp>//this algorithm only works with positive, whole numbers. //O(2n) time complexity where n is the summation of the whole list to be sorted. //O(3n) space complexity.

  1. include<iostream>
  2. include<vector>

using namespace std;

void distribute( int dist, vector<int> &List)//*beads* go down into different buckets using gravity (addition). {

   if (dist > List.size() )
       List.resize(dist,0); //resize if too big for current vector
   for (int i=0; i < dist; i++)
       List[i] = List[i]+1;

}

int main() {

   vector<int> list;
   vector<int> list2;
   int myints[] = {5,3,1,7,4,1,1};
   vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
   cout << "#1 Beads falling down: ";
   for (int i=0; i < fifth.size(); i++)
       distribute (fifth[i], list);
   cout << endl;
   cout <<endl<< "Beads on their sides: ";
   for (int i=0; i < list.size(); i++)
       cout << " " << list[i];
   cout << endl;	
   //second part
   cout << "#2 Beads right side up: ";
   for (int i=0; i < list.size(); i++)
       distribute (list[i], list2);
   cout << endl;
   cout <<endl<< "Sorted list/array";
   for (int i=0; i < list2.size(); i++)
       cout << " " << list2[i];
   cout << endl;
   return 0;

}</lang>

Output:

Beads falling down:

Beads on their sides: 7 4 4 3 2 1 1 Beads right side up:

Sorted list/array 7 5 4 3 1 1 1

Fortran

Works with: Fortran version 2003
Works with: Fortran version 95

removing the iso_fortran_env as explained in code

This implementation suffers the same problems of the C implementation: if the maximum value in the array to be sorted is very huge, likely there will be not enough free memory to complete the task. Nonetheless, if the Fortran implementation would use "silently" sparse arrays and a compact representation for "sequences" of equal values in an array, then this very same code would run fine even with large integers.

<lang fortran>program BeadSortTest

 use iso_fortran_env 
 ! for ERROR_UNIT; to make this a F95 code,
 ! remove prev. line and declare ERROR_UNIT as an
 ! integer parameter matching the unit associated with
 ! standard error
 integer, dimension(7) :: a = (/ 7, 3, 5, 1, 2, 1, 20 /)
 call beadsort(a)
 print *, a

contains

 subroutine beadsort(a)
   integer, dimension(:), intent(inout) :: a
   integer, dimension(maxval(a), maxval(a)) :: t
   integer, dimension(maxval(a)) :: s
   integer :: i, m
   m = maxval(a)
   
   if ( any(a < 0) ) then
      write(ERROR_UNIT,*) "can't sort"
      return
   end if
   t = 0
   forall(i=1:size(a)) t(i, 1:a(i)) = 1  ! set up abacus
   forall(i=1:m)             ! let beads "fall"; instead of
      s(i) = sum(t(:, i))    ! moving them one by one, we just
      t(:, i) = 0            ! count how many should be at bottom,
      t(1:s(i), i) = 1       ! and then "reset" and set only those
   end forall
   
   forall(i=1:size(a)) a(i) = sum(t(i,:))
   
 end subroutine beadsort

end program BeadSortTest</lang>

Haskell

<lang haskell>import Data.List

beadSort :: [Int] -> [Int] beadSort = map sum. transpose. transpose. map (flip replicate 1)</lang> Example; <lang haskell>*Main> beadSort [2,4,1,3,3] [4,3,3,2,1]</lang>

J

<lang j>bead=: [: +/ #"0&1</lang>

Example use:

<lang> bead bead 2 4 1 3 3 4 3 3 2 1

  bead bead 5 3 1 7 4 1 1

7 5 4 3 1 1 1</lang>

Octave

Translation of: Fortran

<lang octave>function sorted = beadsort(a)

 sorted = a;
 m = max(a);
 if ( any(a < 0) )
   error("can't sort");
 endif
 t = zeros(m, m);
 for i = 1:numel(a)
   t(i, 1:a(i)) = 1;
 endfor
 for i = 1:m
   s = sum(t(:, i));
   t(:, i) = 0;
   t(1:s, i) = 1;
 endfor
 for i = 1:numel(a)
   sorted(i) = sum(t(i, :));
 endfor

endfunction

beadsort([5, 7, 1, 3, 1, 1, 20])</lang>

Tcl

<lang tcl>package require Tcl 8.5

proc beadsort numList {

   # Special case: empty list is empty when sorted.
   if {![llength $numList]} return
   # Set up the abacus...
   foreach n $numList {

for {set i 0} {$i<$n} {incr i} { dict incr vals $i }

   }
   # Make the beads fall...
   foreach n [dict values $vals] {

for {set i 0} {$i<$n} {incr i} { dict incr result $i }

   }
   # And the result is...
   dict values $result

}

  1. Demonstration code

puts [beadsort {5 3 1 7 4 1 1}]</lang> Output:

7 5 4 3 1 1 1