├── .gitignore ├── README.md ├── appendix-3 ├── spacemod.cpp └── timemod.c ├── part-1 ├── column-1 │ ├── Makefile │ ├── bitsort.c │ ├── bitsortgen.c │ ├── notes.txt │ ├── qsortints.c │ ├── sortints.cpp │ └── spacebitsort.c ├── column-2 │ ├── Makefile │ ├── gcd.c │ ├── myrotate-2.cpp │ ├── notes.txt │ ├── rotate.c │ ├── sign.c │ └── squash.c ├── column-3 │ ├── Makefile │ ├── i18n.c │ ├── notes.txt │ └── seven-seg.c ├── column-4 │ ├── Makefile │ ├── bsearch-array.c │ └── notes.txt └── column-5 │ ├── notes.txt │ └── search.c ├── part-2 ├── column-7 │ └── timemod0.c ├── column-8 │ └── maxsum.c └── column-9 │ ├── genbins.c │ ├── macfun.c │ ├── maxsum.c │ ├── rotate.c │ └── search.c └── part-3 ├── column-11 ├── SortAnim.java └── sort.cpp ├── column-12 └── sortedrand.cpp ├── column-13 ├── genbins.c └── sets.cpp ├── column-14 ├── priqueue.cpp └── sort.cpp └── column-15 ├── longdup.c ├── markov.c ├── markovhash.c ├── markovlet.c ├── wordfreq.c ├── wordfreq.cpp └── wordlist.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Libraries 5 | *.lib 6 | *.a 7 | 8 | # Shared objects (inc. Windows DLLs) 9 | *.dll 10 | *.so 11 | *.so.* 12 | *.dylib 13 | 14 | # Executables 15 | *.exe 16 | *.out 17 | *.app 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ppearls 2 | ======= 3 | 4 | Programming Pearls Prep work 5 | 6 | Base from: 7 | 8 | http://www.cs.bell-labs.com/cm/cs/pearls/code.html 9 | -------------------------------------------------------------------------------- /appendix-3/spacemod.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* spacemod.cpp -- simple model for C++ space */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | #define MEASURE(T, text) { \ 10 | cout << text << "\t"; \ 11 | cout << sizeof(T) << "\t"; \ 12 | int lastp = 0; \ 13 | for (int i = 0; i < 11; i++) { \ 14 | T *p = new T; \ 15 | int thisp = (int) p; \ 16 | if (lastp != 0) \ 17 | cout << " " << thisp - lastp; \ 18 | lastp = thisp; \ 19 | } \ 20 | cout << "\n"; \ 21 | } 22 | 23 | // Must use macros; templates give funny answers 24 | 25 | template 26 | void measure(char *text) 27 | { cout << " measure: " << text << "\t"; 28 | cout << sizeof(T) << "\n"; 29 | } 30 | 31 | struct structc { char c; }; 32 | struct structic { int i; char c; }; 33 | struct structip { int i; structip *p; }; 34 | struct structdc { double d; char c; }; 35 | struct structcd { char c; double d; }; 36 | struct structcdc { char c1; double d; char c2; }; 37 | struct structiii { int i1; int i2; int i3; }; 38 | struct structiic { int i1; int i2; char c; }; 39 | struct structc12 { char c[12]; }; 40 | struct structc13 { char c[13]; }; 41 | struct structc28 { char c[28]; }; 42 | struct structc29 { char c[29]; }; 43 | struct structc44 { char c[44]; }; 44 | struct structc45 { char c[45]; }; 45 | struct structc60 { char c[60]; }; 46 | struct structc61 { char c[61]; }; 47 | 48 | int main() 49 | { cout << "Raw sizeof"; 50 | cout << "\nsizeof(char)=" << sizeof(char); 51 | cout << " sizeof(short)=" << sizeof(short); 52 | cout << " sizeof(int)=" << sizeof(int); 53 | cout << "\nsizeof(float)=" << sizeof(float); 54 | cout << " sizeof(struct *)=" << sizeof(structc *); 55 | cout << " sizeof(long)=" << sizeof(long); 56 | cout << "\nsizeof(double)=" << sizeof(double); 57 | 58 | cout << "\n\nMEASURE macro\n"; 59 | MEASURE(int, "int"); 60 | MEASURE(structc, "structc"); 61 | MEASURE(structic, "structic"); 62 | MEASURE(structip, "structip"); 63 | MEASURE(structdc, "structdc"); 64 | MEASURE(structcd, "structcd"); 65 | MEASURE(structcdc, "structcdc"); 66 | MEASURE(structiii, "structiii"); 67 | MEASURE(structiic, "structiic"); 68 | MEASURE(structc12, "structc12"); 69 | MEASURE(structc13, "structc13"); 70 | MEASURE(structc28, "structc28"); 71 | MEASURE(structc29, "structc29"); 72 | MEASURE(structc44, "structc44"); 73 | MEASURE(structc45, "structc45"); 74 | MEASURE(structc60, "structc60"); 75 | MEASURE(structc61, "structc61"); 76 | 77 | 78 | cout << "\nmeasure template (strange results)\n"; 79 | // Uncomment below lines to see answers change 80 | measure("int"); 81 | // measure("structc"); 82 | // measure("structic"); 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /appendix-3/timemod.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* timemod.c -- Produce table of C run time costs */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAXN 100000 12 | int x[MAXN]; 13 | int startn = 5000; 14 | int n; 15 | 16 | /* FUNCTIONS TO BE TIMED */ 17 | 18 | int intcmp(int *i, int *j) 19 | { return *i - *j; } 20 | 21 | #define swapmac(i, j) { t = x[i]; x[i] = x[j]; x[j] = t; } 22 | 23 | void swapfunc(int i, int j) 24 | { int t = x[i]; 25 | x[i] = x[j]; 26 | x[j] = t; 27 | } 28 | 29 | #define maxmac(a, b) ((a) > (b) ? (a) : (b)) 30 | 31 | int maxfunc(int a, int b) 32 | { return a > b ? a : b; } 33 | 34 | 35 | /* WORKHORSE */ 36 | 37 | #define T(s) printf("%s (n=%d)\n", s, n); 38 | #define TRIALS 5 39 | #define M(op) \ 40 | printf(" %-22s", #op); \ 41 | k = 0; \ 42 | timesum = 0; \ 43 | for (ex = 0; ex < TRIALS; ex++) { \ 44 | start = clock(); \ 45 | for (i = 1; i <= n; i++) { \ 46 | fi = (float) i; \ 47 | for (j = 1; j <= n; j++) { \ 48 | op; \ 49 | } \ 50 | } \ 51 | t = clock()-start; \ 52 | printf("%6d", t); \ 53 | timesum += t; \ 54 | } \ 55 | nans = 1e9 * timesum / ((double) \ 56 | n*n * TRIALS * CLOCKS_PER_SEC); \ 57 | printf("%8.0f\n", nans); 58 | 59 | 60 | int main() 61 | { int i, j, k; 62 | float fi, fj, fk; 63 | int t, ex, timesum, start, globalstart; 64 | double nans; 65 | globalstart = clock(); 66 | for (i = 0; i < n; i++) 67 | x[i] = rand(); 68 | n = startn; 69 | printf("C Time Cost Model, n=%d\n", n); 70 | T("Integer Arithmetic"); 71 | M({}); 72 | M(k++); 73 | M(k = i + j); 74 | M(k = i - j); 75 | M(k = i * j); 76 | M(k = i / j); 77 | M(k = i % j); 78 | M(k = i & j); 79 | M(k = i | j); 80 | T("Floating Point Arithmetic"); 81 | M(fj=j;); 82 | M(fj=j; fk = fi + fj;); 83 | M(fj=j; fk = fi - fj;); 84 | M(fj=j; fk = fi * fj;); 85 | M(fj=j; fk = fi / fj;); 86 | T("Array Operations"); 87 | M(k = i + j); 88 | M(k = x[i] + j); 89 | M(k = i + x[j]); 90 | M(k = x[i] + x[j]); 91 | T("Comparisons"); 92 | M(if (i < j) k++); 93 | M(if (x[i] < x[j]) k++); 94 | T("Array Comparisons and Swaps"); 95 | M(k = (x[i] j) ? i : j); 101 | M(k = maxmac(i, j)); 102 | M(k = maxfunc(i, j)); 103 | n = startn / 5; 104 | T("Math Functions"); 105 | M(fk = j+fi;); 106 | M(k = rand();); 107 | M(fk = sqrt(j+fi)); 108 | M(fk = sin(j+fi)); 109 | M(fk = sinh(j+fi)); 110 | M(fk = asin(j+fi)); 111 | M(fk = cos(j+fi)); 112 | M(fk = tan(j+fi)); 113 | n = startn / 10; 114 | T("Memory Allocation"); 115 | M(free(malloc(16));); 116 | M(free(malloc(100));); 117 | M(free(malloc(2000));); 118 | 119 | /* Possible additions: input, output, malloc */ 120 | printf(" Secs: %4.2f\n", 121 | ((double) clock()-globalstart) 122 | / CLOCKS_PER_SEC); 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /part-1/column-1/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Need to turn to programs to lib. Non-recursive make, unit tests... 3 | # 4 | .PHONY : all clean check 5 | 6 | TARGETS := bitsort bitsortgen qsortints spacebitsort sortints 7 | CC := gcc 8 | CFLAGS := -Wall -Werror 9 | CXXFLAGS := $(CFLAGS) 10 | 11 | all: $(TARGETS) 12 | 13 | clean: 14 | $(RM) $(TARGETS) 15 | -------------------------------------------------------------------------------- /part-1/column-1/bitsort.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* bitsort.c -- bitmap sort from Column 1 5 | * Sort distinct integers in the range [0..N-1] 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | /* 12 | * How would you implement bit vectors using bitwise logical operations (such 13 | * as and, or and shift)? 14 | * 15 | * Given e.g. 165 (1010 0101) to store: 16 | * 17 | * a[1010 0101>>5] = 1 << (1010 0101 & 0x1F) 18 | * a[101] = 1 << 0 0101 19 | * a[5] = 1 << 5 20 | * a[5] = 0010 0000; well, plus a lot more leading 0's. 21 | */ 22 | #define BITSPERWORD 32 // err uint32_t ... 23 | #define SHIFT 5 // log2(BITSPERWORD); i.e. how many numbers we can 24 | // store per element in the array[]. 25 | #define MASK 0x1F // i.e. 0001 1111 (5 bits) to mask of all but the 26 | // contents. 27 | #define N 10000000 28 | 29 | int a[1 + N/BITSPERWORD]; 30 | 31 | void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } 32 | void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } 33 | int tst(int i) { return a[i>>SHIFT] & (1<<(i & MASK)); } 34 | 35 | int main() 36 | { 37 | /* 38 | * Define for word-parallel init 39 | */ 40 | #ifndef PARALLEL_INIT 41 | int i; 42 | 43 | for (i = 0; i < N; i++) 44 | clr(i); 45 | #else 46 | int top = 1 + N/BITSPERWORD; 47 | 48 | for (i = 0; i < top; i++) 49 | a[i] = 0; 50 | #endif 51 | 52 | // Need to check other scanf return values for error. 53 | while (scanf("%d", &i) != EOF) { 54 | if ((i < 0) || (i >= N)) { 55 | fprintf(stderr, "Out of range 0 >= %d < %d\n", i, N); 56 | exit(1); 57 | } 58 | if (tst(i)) { 59 | fprintf(stderr, "Already passed %d\n", i); 60 | exit(1); 61 | } 62 | set(i); 63 | } 64 | 65 | for (i = 0; i < N; i++) 66 | if (tst(i)) 67 | printf("%d\n", i); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /part-1/column-1/bitsortgen.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* bitsortgen.c -- gen $1 distinct integers from U[0,$2) 5 | * 6 | * This is the Fisher–Yates shuffle... 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | uint32_t *x; 15 | 16 | /* 17 | * Think of it like a pack of sorted pack of cards. 18 | * 19 | * Pick a random card out of the deck, and replace with the first card of the 20 | * deck. 21 | * 22 | * Continue until you have k cards. 23 | * 24 | * Starting with: 25 | * 26 | * x[i] = i; for [0,n] 27 | * 28 | * Generate a random number in the range r=[a=[0,n],n] 29 | * 30 | * 0...a......n 31 | * ^^^^^^ 32 | * 33 | * Swap x[r] with x[a]. 34 | * 35 | * i.e. guaranteed to pick random unused number. 36 | * 37 | */ 38 | 39 | uint32_t randint (uint32_t a, uint32_t b) 40 | { 41 | uint32_t range; 42 | uint32_t r, max; 43 | 44 | /* 45 | * We want a number in the range a..b. 46 | */ 47 | range = b - a + 1; 48 | 49 | /* 50 | * Discard top random numbers for uniform distribution in this range, by 51 | * removing the remainder. 52 | */ 53 | max = RAND_MAX; 54 | if (range < RAND_MAX) { 55 | max -= (RAND_MAX % range); 56 | } 57 | 58 | do { 59 | r = rand(); 60 | } while (r >= max); 61 | 62 | 63 | // if (RAND_MAX * RAND_MAX < INT_MAX) 64 | 65 | // if (b > RAND_MAX) { 66 | // r += RAND_MAX * rand(); 67 | // } 68 | 69 | r %= range; 70 | 71 | return (a + r); 72 | } 73 | 74 | int main(int argc, const char *argv[]) 75 | { 76 | uint32_t i, k, n, t, p; 77 | 78 | if (argc < 2) { 79 | fprintf(stderr, "Usage %s: \n", 80 | argv[0]); 81 | exit(1); 82 | } 83 | 84 | k = atoi(argv[1]); 85 | n = atoi(argv[2]); 86 | 87 | if ((k <= 0) || (n <= k)) { 88 | fprintf(stderr, "Usage %s: <1..n-1> \n", 89 | argv[0]); 90 | exit(1); 91 | } 92 | 93 | //srand((unsigned) time(NULL)); 94 | srand(0);//could make arg. 95 | 96 | x = malloc(n * sizeof(*x)); 97 | if (!x) { 98 | fprintf(stderr, "No mem!\n"); 99 | exit(1); 100 | } 101 | 102 | for (i = 0; i < n; i++) 103 | x[i] = i; 104 | 105 | for (i = 0; i < k; i++) { 106 | p = randint(i, n-1); 107 | //printf("Result %u\n", p); 108 | t = x[p]; 109 | x[p] = x[i]; 110 | x[i] = t; 111 | printf("%d\n", x[i]); 112 | } 113 | 114 | free(x); 115 | 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /part-1/column-1/notes.txt: -------------------------------------------------------------------------------- 1 | Go back one step and define the problem: 2 | 3 | o Inputs 4 | o Outputs 5 | o Constraints 6 | 7 | log,b(m*n) = log,b(m) + log,b(n) 8 | 9 | log,b(m/n) = log,b(m) - log,b(n) 10 | 11 | log,b(m^n) = n * log,b(m) 12 | 13 | log,b(x) = log,d(x) 14 | ------- 15 | log,d(b) 16 | 17 | x^n = x^a+b = x^a * x^b 18 | -------------------------------------------------------------------------------- /part-1/column-1/qsortints.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* qsortints.c -- Sort input set of integers using qsort */ 5 | 6 | #include 7 | #include 8 | 9 | int intcomp (const void *x, const void *y) 10 | { 11 | return (*(int *)x - *(int *)y); 12 | } 13 | 14 | int a[1000000]; 15 | 16 | int main() 17 | { 18 | int i, n=0; 19 | 20 | while (scanf("%d", &a[n]) != EOF) 21 | n++; 22 | 23 | qsort(a, n, sizeof(int), intcomp); 24 | 25 | for (i = 0; i < n; i++) 26 | printf("%d\n", a[i]); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /part-1/column-1/sortints.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* sortints.cpp -- Sort input set of integers using STL set */ 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main() 12 | { 13 | set S; 14 | int i; 15 | set::iterator j; 16 | 17 | while (cin >> i) 18 | S.insert(i); 19 | 20 | for (j = S.begin(); j != S.end(); ++j) 21 | cout << *j << "\n"; 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /part-1/column-1/spacebitsort.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* Based on bitsort.c -- bitmap sort from Column 1 5 | * Sort distinct integers in the range [0..N-1] 6 | * 7 | * See: 8 | * http://research.swtch.com/sparse 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #define BITSPERWORD 32 15 | #define SHIFT 5 16 | #define MASK 0x1F 17 | #define N 10000000 18 | 19 | #define TOP (1 + N/BITSPERWORD) 20 | int a[TOP]; 21 | int from[TOP]; 22 | int to[TOP]; 23 | const int dtop = TOP; 24 | 25 | void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } 26 | void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } 27 | int tst(int i) { return a[i>>SHIFT] & (1<<(i & MASK)); } 28 | 29 | bool 30 | is_member (int subscript, int top) 31 | { 32 | return ((from[subscript] < top) && 33 | (to[from[subscript]] == subscript)); 34 | } 35 | 36 | int main() 37 | { 38 | int i; 39 | int subscript; 40 | int top = 0; 41 | 42 | while (scanf("%d", &i) != EOF) { 43 | subscript = (i>>SHIFT); 44 | if (!is_member(subscript, top)) { 45 | from[subscript] = top; 46 | to[top] = subscript; 47 | a[subscript] = 0; 48 | top++; 49 | } 50 | 51 | set(i); 52 | } 53 | 54 | for (i = 0; i < N; i++) { 55 | subscript = (i>>SHIFT); 56 | if (is_member(subscript, top)) { 57 | if (tst(i)) { 58 | printf("%d\n", i); 59 | } 60 | } 61 | } 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /part-1/column-2/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Need to turn to programs to lib. Non-recursive make, unit tests... 3 | # 4 | .PHONY : all clean check 5 | 6 | TARGETS := rotate sign squash myrotate myrotate-2 7 | CC := gcc 8 | CFLAGS := -Wall -Werror 9 | CXXFLAGS := $(CFLAGS) 10 | 11 | all: $(TARGETS) 12 | 13 | clean: 14 | $(RM) $(TARGETS) 15 | -------------------------------------------------------------------------------- /part-1/column-2/gcd.c: -------------------------------------------------------------------------------- 1 | 2 | int euclid_gcd (int a, int b) 3 | { 4 | int t; 5 | 6 | if (!a) return (b); 7 | if (!b) return (a); 8 | 9 | if (a > b) { 10 | t = b; 11 | b = a; 12 | a = t; 13 | } 14 | 15 | while (b != 0) { 16 | t = b; 17 | b = a % b; 18 | a = t; 19 | } 20 | 21 | return (a); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /part-1/column-2/myrotate-2.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include // std::cout 3 | #include // std::rotate 4 | #include // std::vector 5 | 6 | using namespace std; 7 | 8 | int main (int argc, const char *argv[]) 9 | { 10 | std::vector buf; 11 | 12 | if (argc < 2) { 13 | fprintf(stderr, "Usage: %s \n", argv[0]); 14 | exit(1); 15 | } 16 | 17 | std::rotate(myvector.begin(),myvector.begin()+3,myvector.end()); 18 | 19 | r = atoi(argv[1]); 20 | // note works for negative as well. 21 | 22 | n = strlen(argv[2]); 23 | 24 | if ((r > n) || (r < -n)) { 25 | fprintf(stderr, "Usage: %s [<%d>] < <%d>\n", 26 | argv[0], r, n); 27 | exit(1); 28 | } 29 | 30 | buf = strdup(argv[2]); 31 | 32 | rotate(); 33 | 34 | printf("input : %s\n", argv[2]); 35 | printf("output: %*s%s\n", 36 | r, "", 37 | buf); 38 | 39 | free(buf); 40 | 41 | int main () { 42 | 43 | // set some values: 44 | for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9 45 | 46 | // print out content: 47 | std::cout << "myvector contains:"; 48 | for (std::vector::iterator it=myvector.begin(); it!=myvector.end(); ++it) 49 | std::cout << ' ' << *it; 50 | std::cout << '\n'; 51 | 52 | return 0; 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /part-1/column-2/notes.txt: -------------------------------------------------------------------------------- 1 | Number of permutations: 2 | 3 | for a given n 4 | 5 | n * (n-1) * (n-2) .... 1 6 | = n! 7 | 8 | nPr = n! / (n-r)! 9 | 10 | i.e. 11 | 12 | n * n-1 * n-2 * r+1 13 | 14 | nCr = n! / (r!(n-r)!) 15 | 16 | 17 | The juggle rotate works like so: 18 | 19 | For r=1, it's obvious that we store the first value in a temp, and move the 20 | values into the dst, until we get all the way back around, i.e.: 21 | 22 | 23 | i = 0; 24 | t = [i] 25 | 26 | while (0 != ((i++)%n) { 27 | [i-1] = [i]; 28 | } 29 | [i-1] = t; 30 | 31 | Since otherwise we'd run for ever, and keep shifting forever (this is an algo 32 | for r>1). 33 | 34 | But, since we can move from cur location to desired in one go, we do so until 35 | we get to the end, where 36 | 37 | 38 | It helps to think as a infinitely repeating array (%n) 39 | 40 | r=4,n=6 41 | 42 | t=0 43 | ? 1 2 3 4 5 44 | ^ ^ ^ ^ 45 | 4 1 2 3 ? 5 4 1 2 3 ? 5 46 | ^ ^ ^ ^ 47 | 4 1 ? 3 2 5 4 1 ? 3 2 5 4 1 ? 3 2 5 48 | ^ ^ ^ ^ 49 | Back to start, so are done. 50 | 4 1 0 3 2 5 51 | 52 | Next char: 53 | t=1 54 | 4 ? 0 3 2 5 55 | ^ ^ ^ ^ 56 | 4 5 0 3 2 ? 4 5 0 3 2 ? 57 | ^ ^ ^ ^ 58 | 4 5 0 ? 2 3 4 5 0 ? 2 3 4 5 0 ? 2 3 59 | ^ ^ ^ ^ 60 | Back to start, so are done. 61 | 4 5 0 1 2 3 62 | 63 | i.e. keep going till back where we started. But the question is did we visit 64 | every element? 65 | 66 | Want number of exchanges to be "n" 67 | 68 | For r=1, we do n exchanges. 69 | 70 | But, if we are back where we started, and we didn't do n exchanges, then we 71 | need to start at the next place. 72 | 73 | How many will we do in total then? 74 | 75 | If we ended up back where we started, but did less than n, we know that we 76 | have: 77 | 78 | x * y exchanges == n 79 | 80 | Now if n % r = 0, i.e. no remainder, the answer is: 81 | 82 | r * n/r exchanges = n 83 | 84 | e.g. (5,10) = 5 * 2 = 10 85 | 86 | However, using modulo mathematics: 87 | 88 | (6,10) 89 | 90 | 0+6 % 10 = 6 91 | 6+6 % 10 = 2 92 | 2+6 % 10 = 8 93 | 8+6 % 10 = 4 94 | 4+6 % 10 = 0 <- start 95 | 96 | 1+6 ... 97 | 98 | 6 10 99 | --- and ---- 100 | ? ? 101 | 102 | The question is really what can I fit into r, that I can also fit into n? 103 | 104 | gcd(6,10) = 2. 105 | 10 / 2 = 5 106 | 107 | 6 10 108 | -- ---- = 5 109 | 2 2 110 | 111 | -------------------------------------------------------------------------------- /part-1/column-2/rotate.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* rotate.c -- time algorithms for rotating a vector 5 | Input lines: 6 | algnum numtests n rotdist 7 | algnum: 8 | 1: reversal algorithm 9 | 2: juggling algorithm 10 | 22: juggling algorithm with mod rather than if 11 | 3: gcd algorithm 12 | 4: slide (don't rotate): baseline alg for timing 13 | To test the algorithms, recompile and change main to call testrot 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #define MAXN 10000000 21 | 22 | int x[MAXN]; 23 | int rotdist, n; 24 | 25 | /* Alg 1: Rotate by reversal */ 26 | 27 | void reverse(int i, int j) 28 | { 29 | int t; 30 | while (i < j) { 31 | t = x[i]; x[i] = x[j]; x[j] = t; 32 | i++; 33 | j--; 34 | } 35 | } 36 | 37 | void revrot(int rotdist, int n) 38 | { 39 | reverse(0, rotdist-1); 40 | reverse(rotdist, n-1); 41 | reverse(0, n-1); 42 | } 43 | 44 | /* Alg 2: Juggling (dolphin) rotation */ 45 | 46 | int gcd(int i, int j) 47 | { 48 | int t; 49 | while (i != 0) { 50 | if (j >= i) 51 | j -= i; 52 | else { 53 | t = i; i = j; j = t; 54 | } 55 | } 56 | return j; 57 | } 58 | 59 | void jugglerot(int rotdist, int n) 60 | { 61 | int cycles, i, j, k, t; 62 | cycles = gcd(rotdist, n); 63 | printf("gcd(%d, %d) = %d\n", 64 | rotdist, n, cycles); 65 | 66 | for (i = 0; i < cycles; i++) { 67 | /* move i-th values of blocks */ 68 | t = x[i]; 69 | printf("t = [%d]\n", i); 70 | j = i; 71 | for (;;) { 72 | k = j + rotdist; 73 | if (k >= n) 74 | k -= n; 75 | if (k == i) 76 | break; 77 | printf("[%d] = [%d]\n", j, k); 78 | x[j] = x[k]; 79 | j = k; 80 | } 81 | printf("[%d] = t\n", j); 82 | x[j] = t; 83 | } 84 | } 85 | 86 | void jugglerot2(int rotdist, int n) 87 | { 88 | int cycles, i, j, k, t; 89 | cycles = gcd(rotdist, n); 90 | printf("gcd(%d, %d) = %d\n", 91 | rotdist, n, cycles); 92 | for (i = 0; i < cycles; i++) { 93 | /* move i-th values of blocks */ 94 | t = x[i]; 95 | printf("t = [%d]\n", i); 96 | j = i; 97 | for (;;) { 98 | /* Replace with mod below 99 | k = j + rotdist; 100 | if (k >= n) 101 | k -= n; 102 | */ 103 | k = (j + rotdist) % n; 104 | if (k == i) 105 | break; 106 | printf("[%d] = [%d]\n", j, k); 107 | x[j] = x[k]; 108 | j = k; 109 | } 110 | printf("[%d] = t\n", j); 111 | x[j] = t; 112 | } 113 | } 114 | 115 | /* Alg 3: Recursive rotate (using gcd structure) */ 116 | 117 | void swap(int i, int j, int k) /* swap x[i..i+k-1] with x[j..j+k-1] */ 118 | { 119 | int t; 120 | while (k-- > 0) { 121 | t = x[i]; x[i] = x[j]; x[j] = t; 122 | i++; 123 | j++; 124 | } 125 | 126 | } 127 | 128 | void gcdrot(int rotdist, int n) 129 | { 130 | int i, j, p; 131 | if (rotdist == 0 || rotdist == n) 132 | return; 133 | i = p = rotdist; 134 | j = n - p; 135 | while (i != j) { 136 | /* invariant: 137 | x[0 ..p-i ] is in final position 138 | x[p-i..p-1 ] = a (to be swapped with b) 139 | x[p ..p+j-1] = b (to be swapped with a) 140 | x[p+j..n-1 ] in final position 141 | */ 142 | if (i > j) { 143 | swap(p-i, p, j); 144 | i -= j; 145 | } else { 146 | swap(p-i, p+j-i, i); 147 | j -= i; 148 | } 149 | } 150 | swap(p-i, p, i); 151 | } 152 | 153 | int isogcd(int i, int j) 154 | { 155 | if (i == 0) return j; 156 | if (j == 0) return i; 157 | while (i != j) { 158 | if (i > j) 159 | i -= j; 160 | else 161 | j -= i; 162 | } 163 | return i; 164 | } 165 | 166 | void testgcd() 167 | { 168 | int i,j; 169 | while (scanf("%d %d", &i, &j) != EOF) 170 | printf("%d\n", isogcd(i,j) ); 171 | } 172 | 173 | /* Test all algs */ 174 | 175 | void slide(int rotdist, int n) /* Benchmark: slide left rotdist (lose 0..rotdist-1) */ 176 | { 177 | int i; 178 | 179 | for (i = rotdist; i < n; i++) 180 | x[i-rotdist] = x[i]; 181 | } 182 | 183 | void initx() 184 | { 185 | int i; 186 | for (i = 0; i < n; i++) 187 | x[i] = i; 188 | } 189 | 190 | void printx() 191 | { 192 | int i; 193 | for (i = 0; i < n; i++) 194 | printf(" %d", x[i]); 195 | printf("\n"); 196 | } 197 | 198 | void roterror() 199 | { 200 | fprintf(stderr, " rotate bug %d %d\n", n, rotdist); 201 | printx(); 202 | exit (1); 203 | } 204 | 205 | void checkrot() 206 | { 207 | int i; 208 | for (i = 0; i < n-rotdist; i++) 209 | if (x[i] != i+rotdist) 210 | roterror(); 211 | for (i = 0; i < rotdist; i++) 212 | if (x[n-rotdist+i] != i) 213 | roterror(); 214 | } 215 | 216 | void testrot() 217 | { 218 | for (n = 1; n <= 20; n++) { 219 | printf(" testing n=%d\n", n); 220 | for (rotdist = 0; rotdist <= n; rotdist++) { 221 | /* printf(" testing rotdist=%d\n", rotdist); */ 222 | initx(); revrot(rotdist, n); checkrot(); 223 | initx(); jugglerot(rotdist, n); checkrot(); 224 | initx(); jugglerot2(rotdist, n); checkrot(); 225 | initx(); gcdrot(rotdist, n); checkrot(); 226 | } 227 | } 228 | } 229 | 230 | /* Timing */ 231 | 232 | void timedriver() 233 | { 234 | int i, algnum, numtests, start, clicks; 235 | while (scanf("%d %d %d %d", &algnum, &numtests, &n, &rotdist) != EOF) { 236 | initx(); 237 | start = clock(); 238 | for (i = 0; i < numtests; i++) { 239 | if (algnum == 1) 240 | revrot(rotdist, n); 241 | else if (algnum == 2) 242 | jugglerot(rotdist, n); 243 | else if (algnum == 22) 244 | jugglerot2(rotdist, n); 245 | else if (algnum == 3) 246 | gcdrot(rotdist, n); 247 | else if (algnum == 4) 248 | slide(rotdist, n); 249 | } 250 | clicks = clock() - start; 251 | printf("%d\t%d\t%d\t%d\t%d\t%g\n", 252 | algnum, numtests, n, rotdist, clicks, 253 | 1e9*clicks/((float) CLOCKS_PER_SEC*n*numtests)); 254 | } 255 | } 256 | 257 | /* Main */ 258 | 259 | int main() 260 | { 261 | testrot(); 262 | //timedriver(); 263 | return 0; 264 | } 265 | -------------------------------------------------------------------------------- /part-1/column-2/sign.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* sign.c -- sign each line of a file for finding anagrams 5 | The input line "stop" gives the output line "opst stop" 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #define WORDMAX 100 12 | 13 | int charcomp(const void *x, const void *y) 14 | { 15 | return *(char *)x - *(char *)y; 16 | } 17 | 18 | int main() 19 | { 20 | char word[WORDMAX], sig[WORDMAX]; 21 | while (scanf("%s", word) != EOF) { 22 | strcpy(sig, word); 23 | qsort(sig, strlen(sig), sizeof(char), charcomp); 24 | printf("%s %s\n", sig, word); 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /part-1/column-2/squash.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* squash.c -- print anagram classes on a single line 5 | The input lines "opst pots" and "opst stop" go to "pots stop" 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #define WORDMAX 100 12 | 13 | int main() 14 | { 15 | char word[WORDMAX], sig[WORDMAX], oldsig[WORDMAX]; 16 | int linenum = 0; 17 | strcpy(oldsig, ""); 18 | while (scanf("%s %s", sig, word) != EOF) { 19 | if (strcmp(oldsig, sig) != 0 && linenum > 0) 20 | printf("\n"); 21 | strcpy(oldsig, sig); 22 | linenum++; 23 | printf("%s ", word); 24 | } 25 | printf("\n"); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /part-1/column-3/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Need to turn to programs to lib. Non-recursive make, unit tests... 3 | # 4 | .PHONY : all clean check 5 | 6 | TARGETS := i18n seven-seg 7 | CC := gcc 8 | CFLAGS := -Wall -Werror 9 | CXXFLAGS := $(CFLAGS) 10 | 11 | all: $(TARGETS) 12 | 13 | clean: 14 | $(RM) $(TARGETS) 15 | -------------------------------------------------------------------------------- /part-1/column-3/i18n.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int 5 | main (int argc, const char *argv[]) 6 | { 7 | #if 0 8 | if (argc < 3) { 9 | fprintf(stderr, "Usage: %s \n", argv[0]); 10 | exit(1); 11 | } 12 | #endif 13 | 14 | printf("%2$d %1$d\n", 1, 2); 15 | printf("%2$*1$d\n", 3, 4); 16 | 17 | return (0); 18 | } 19 | -------------------------------------------------------------------------------- /part-1/column-3/notes.txt: -------------------------------------------------------------------------------- 1 | Don't write a big program when a little one will do. 2 | 3 | Perfection is when there is nothing left to remove. 4 | 5 | Data driven design? 6 | - by input data? 7 | - by output data? 8 | 9 | 10 | Like Perl Formats or i18n support in C. 11 | 12 | http://perldoc.perl.org/perlform.html 13 | 14 | %$ 15 | 16 | Given a day of year and year => Month day of Month 17 | 18 | e.g. 19 | 61st 2004 => 1st day of 2rd Month. 20 | 21 | 22 | Leap year if perfectly divisible by four 23 | Except: years divisible by 100 and not divisible by 400 24 | => truth table 25 | 26 | bool is_leap_year(int y) 27 | { 28 | return ( 29 | 30 | !(y % 4) 31 | && (!(y%100) && (y%400)) 32 | 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- 37 | 38 | Banner: 39 | 40 | ######## 41 | ## 42 | ## 43 | ## 44 | ######## 45 | 46 | ROWS=7 (needs to be odd for middle lines? 47 | 48 | Display is 8 wide by 7 tall 49 | 50 | Encoded as a byte here we have: 51 | 52 | 11111111 53 | 00011000 54 | 00011000 55 | 00011000 56 | 00011000 57 | 00011000 58 | 11111111 59 | 60 | E 61 | 62 | 11111111 63 | 11000000 64 | 11000000 65 | 11111111 66 | 11000000 67 | 11000000 68 | 11111111 69 | 70 | B 71 | 72 | 73 | 11111100 74 | 11000011 75 | 11000011 76 | 11111100 77 | 11000011 78 | 11000011 79 | 11111100 80 | 81 | Could have: 82 | 83 | uint8_t alphabet[NCHARS][NROWS] = { 84 | { 0xff, 0xff, etc }, // A 85 | { 0xff, 0xff, etc }, // B 86 | } 87 | 88 | But this means we get bad cache align, really want to write: 89 | 90 | 91 | for (r=0;r 2 | #include 3 | 4 | 5 | #define BIT(a) 1<<(a) 6 | 7 | // perhaps clearing the inverse would have been easier.. 8 | static int ssd_tbl[] = { 9 | [0x0] = BIT(0)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8), 10 | [0x1] = BIT(4)|BIT(6), 11 | [0x2] = BIT(0)|BIT(1)|BIT(2)|BIT(4)|BIT(5)|BIT(7)|BIT(8), 12 | [0x3] = BIT(0)|BIT(1)|BIT(2)|BIT(4)|BIT(6)|BIT(7)|BIT(8), 13 | [0x4] = BIT(1)|BIT(3)|BIT(4)|BIT(6)|BIT(7)|BIT(8), 14 | [0x5] = BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(6)|BIT(7)|BIT(8), 15 | [0x6] = BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(5)|BIT(6)|BIT(7)|BIT(8), 16 | [0x7] = BIT(2)|BIT(4)|BIT(6)|BIT(7)|BIT(8), 17 | [0x8] = BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8), 18 | [0x9] = BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(6)|BIT(7)|BIT(8), 19 | [0xa] = BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8), 20 | [0xb] = BIT(0)|BIT(1)|BIT(3)|BIT(5)|BIT(6)|BIT(7)|BIT(8), 21 | [0xc] = BIT(0)|BIT(2)|BIT(3)|BIT(5)|BIT(7)|BIT(8), 22 | [0xd] = BIT(0)|BIT(1)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8), 23 | [0xe] = BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(5)|BIT(7)|BIT(8), 24 | [0xf] = BIT(1)|BIT(2)|BIT(3)|BIT(5)|BIT(7)|BIT(8), 25 | }; 26 | 27 | static void 28 | ssd_base (int base, uint16_t input, uint8_t output[]) 29 | { 30 | int i; 31 | 32 | for (i=0; i<5; i++) { 33 | output[4-i] = ssd_tbl[input%base]; 34 | input /= base; 35 | } 36 | } 37 | 38 | static void 39 | ssd_display (uint8_t output[]) 40 | { 41 | int i; 42 | 43 | for (i=0; i<5;i++) { 44 | printf(" %c ", output[i] & BIT(2) ? '_' : ' '); 45 | } 46 | printf("\n"); 47 | 48 | for (i=0; i<5;i++) { 49 | printf("%c%c%c ", 50 | output[i] & BIT(3) ? '|' : ' ', 51 | output[i] & BIT(1) ? '_' : ' ', 52 | output[i] & BIT(4) ? '|' : ' '); 53 | } 54 | printf("\n"); 55 | for (i=0; i<5;i++) { 56 | printf("%c%c%c ", 57 | output[i] & BIT(5) ? '|' : ' ', 58 | output[i] & BIT(0) ? '_' : ' ', 59 | output[i] & BIT(6) ? '|' : ' '); 60 | } 61 | printf("\n"); 62 | } 63 | 64 | int main (void) 65 | { 66 | uint8_t output[5]; 67 | 68 | ssd_base(10, 12345, output); 69 | ssd_display(output); 70 | 71 | ssd_base(10, 6789, output); 72 | ssd_display(output); 73 | 74 | ssd_base(16, 0x0123, output); 75 | ssd_display(output); 76 | 77 | ssd_base(16, 0x4567, output); 78 | ssd_display(output); 79 | 80 | ssd_base(16, 0x89ab, output); 81 | ssd_display(output); 82 | 83 | ssd_base(16, 0xcdef, output); 84 | ssd_display(output); 85 | 86 | return (0); 87 | } 88 | -------------------------------------------------------------------------------- /part-1/column-4/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Need to turn to programs to lib. Non-recursive make, unit tests... 3 | # 4 | .PHONY : all clean check 5 | 6 | TARGETS := bsearch-array 7 | CC := gcc 8 | CFLAGS := -Wall -Werror 9 | CXXFLAGS := $(CFLAGS) 10 | 11 | all: $(TARGETS) 12 | 13 | clean: 14 | $(RM) $(TARGETS) 15 | -------------------------------------------------------------------------------- /part-1/column-4/bsearch-array.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int 6 | bsearch_mine (const int array[], int len, int target) 7 | { 8 | int start, end, probe; 9 | int pos = -1; 10 | 11 | start = 0; 12 | end = len; 13 | while (start < end) { 14 | probe = (start + end) / 2; 15 | 16 | if (target == array[probe]) { 17 | pos = probe; 18 | break; 19 | } else if (target < array[probe]) { 20 | end = probe; 21 | } else { 22 | start = probe + 1; 23 | } 24 | } 25 | 26 | return (pos); 27 | } 28 | 29 | int 30 | main (int argc, const char *argv[]) 31 | { 32 | int array[argc]; 33 | int i, t, p; 34 | 35 | if (argc<3) { 36 | fprintf(stderr, "Usage: %s \n", argv[0]); 37 | exit(1); 38 | } 39 | 40 | t = atoi(argv[1]); 41 | 42 | for (i=0; i' : ' ', 53 | i, array[i]); 54 | } 55 | if (p<0) { 56 | printf("Not found!\n"); 57 | } 58 | 59 | return (0); 60 | } 61 | -------------------------------------------------------------------------------- /part-1/column-4/notes.txt: -------------------------------------------------------------------------------- 1 | 1) Problem Definition 2 | 2) Algorithm Design 3 | 3) Data Structure Selection 4 | 5 | 6 | Does sorted array x[0..n-1] contain t ? 7 | Answer stored in p (-1 == not found) where x[p] == t 8 | 9 | -------------------------------------------------------------------------------- /part-1/column-5/notes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alxn/ppearls/17eee1d7d5685716ce29da8ddf1421f80323c03f/part-1/column-5/notes.txt -------------------------------------------------------------------------------- /part-1/column-5/search.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* search.c -- test and time binary and sequential search 5 | Select one of three modes by editing main() below. 6 | 1.) Probe one function 7 | 2.) Test one function extensively 8 | 3.) Time all functions 9 | Input lines: algnum n numtests 10 | Output lines: algnum n numtests clicks nanosecs_per_elem 11 | See timedriver for algnum codes 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #define MAXN 1000000 19 | 20 | typedef int DataType; 21 | 22 | DataType x[MAXN]; 23 | int n; 24 | 25 | /* Scaffolding */ 26 | 27 | int i = -999999; 28 | #define assert(v) { if ((v) == 0) printf(" binarysearch bug %d %d\n", i, n); } 29 | 30 | /* Alg 1: From Programming Pearls, Column 4: raw transliteration */ 31 | 32 | int binarysearch1(DataType t) 33 | { int l, u, m; 34 | l = 0; 35 | u = n-1; 36 | for (;;) { 37 | if (l > u) 38 | return -1; 39 | m = (l + u) / 2; 40 | if (x[m] < t) 41 | l = m+1; 42 | else if (x[m] == t) 43 | return m; 44 | else /* x[m] > t */ 45 | u = m-1; 46 | } 47 | } 48 | 49 | /* Alg 2: Make binarysearch1 more c-ish */ 50 | 51 | int binarysearch2(DataType t) 52 | { int l, u, m; 53 | l = 0; 54 | u = n-1; 55 | while (l <= u) { 56 | m = (l + u) / 2; 57 | if (x[m] < t) 58 | l = m+1; 59 | else if (x[m] == t) 60 | return m; 61 | else /* x[m] > t */ 62 | u = m-1; 63 | } 64 | return -1; 65 | } 66 | 67 | /* Alg 3: From PP, Col 8 */ 68 | 69 | int binarysearch3(DataType t) 70 | { int l, u, m; 71 | l = -1; 72 | u = n; 73 | while (l+1 != u) { 74 | m = (l + u) / 2; 75 | if (x[m] < t) 76 | l = m; 77 | else 78 | u = m; 79 | } 80 | if (u >= n || x[u] != t) 81 | return -1; 82 | return u; 83 | } 84 | 85 | /* Alg 4: From PP, Col 9 */ 86 | 87 | int binarysearch4(DataType t) 88 | { int l, p; 89 | if (n != 1000) 90 | return binarysearch3(t); 91 | l = -1; 92 | if (x[511] < t) l = 1000 - 512; 93 | if (x[l+256] < t) l += 256; 94 | if (x[l+128] < t) l += 128; 95 | if (x[l+64 ] < t) l += 64; 96 | if (x[l+32 ] < t) l += 32; 97 | if (x[l+16 ] < t) l += 16; 98 | if (x[l+8 ] < t) l += 8; 99 | if (x[l+4 ] < t) l += 4; 100 | if (x[l+2 ] < t) l += 2; 101 | if (x[l+1 ] < t) l += 1; 102 | p = l+1; 103 | if (p >= n || x[p] != t) 104 | return -1; 105 | return p; 106 | } 107 | 108 | /* Alg 9: Buggy, from Programming Pearls, Column 5 */ 109 | 110 | int sorted() 111 | { int i; 112 | for (i = 0; i < n-1; i++) 113 | if (x[i] > x[i+1]) 114 | return 0; 115 | return 1; 116 | } 117 | 118 | int binarysearch9(DataType t) 119 | { int l, u, m; 120 | /* int oldsize, size = n+1; */ 121 | l = 0; 122 | u = n-1; 123 | while (l <= u) { 124 | /* oldsize = size; 125 | size = u - l +1; 126 | assert(size < oldsize); */ 127 | m = (l + u) / 2; 128 | /* printf(" %d %d %d\n", l, m, u); */ 129 | if (x[m] < t) 130 | l = m; 131 | else if (x[m] > t) 132 | u = m; 133 | else { 134 | /* assert(x[m] == t); */ 135 | return m; 136 | } 137 | } 138 | /* assert(x[l] > t && x[u] < t); */ 139 | return -1; 140 | } 141 | 142 | /* Alg 21: Simple sequential search */ 143 | 144 | int seqsearch1(DataType t) 145 | { int i; 146 | for (i = 0; i < n; i++) 147 | if (x[i] == t) 148 | return i; 149 | return -1; 150 | } 151 | 152 | /* Alg 22: Faster sequential search: Sentinel */ 153 | 154 | int seqsearch2(DataType t) 155 | { int i; 156 | DataType hold = x[n]; 157 | x[n] = t; 158 | for (i = 0; ; i++) 159 | if (x[i] == t) 160 | break; 161 | x[n] = hold; 162 | if (i == n) 163 | return -1; 164 | else 165 | return i; 166 | } 167 | 168 | /* Alg 23: Faster sequential search: loop unrolling */ 169 | 170 | int seqsearch3(DataType t) 171 | { int i; 172 | DataType hold = x[n]; 173 | x[n] = t; 174 | for (i = 0; ; i+=8) { 175 | if (x[i] == t) { break; } 176 | if (x[i+1] == t) { i += 1; break; } 177 | if (x[i+2] == t) { i += 2; break; } 178 | if (x[i+3] == t) { i += 3; break; } 179 | if (x[i+4] == t) { i += 4; break; } 180 | if (x[i+5] == t) { i += 5; break; } 181 | if (x[i+6] == t) { i += 6; break; } 182 | if (x[i+7] == t) { i += 7; break; } 183 | } 184 | x[n] = hold; 185 | if (i == n) 186 | return -1; 187 | else 188 | return i; 189 | } 190 | 191 | 192 | /* Scaffolding to probe one algorithm */ 193 | 194 | void probe1() 195 | { int i; 196 | DataType t; 197 | while (scanf("%d %d", &n, &t) != EOF) { 198 | for (i = 0; i < n; i++) 199 | x[i] = 10*i; 200 | printf(" %d\n", binarysearch9(t)); 201 | } 202 | } 203 | 204 | 205 | /* Torture test one algorithm */ 206 | 207 | #define s seqsearch3 208 | void test(int maxn) 209 | { int i; 210 | for (n = 0; n <= maxn; n++) { 211 | printf("n=%d\n", n); 212 | /* distinct elements (plus one at top) */ 213 | for (i = 0; i <= n; i++) 214 | x[i] = 10*i; 215 | for (i = 0; i < n; i++) { 216 | assert(s(10*i) == i); 217 | assert(s(10*i - 5) == -1); 218 | } 219 | assert(s(10*n - 5) == -1); 220 | assert(s(10*n) == -1); 221 | /* equal elements */ 222 | for (i = 0; i < n; i++) 223 | x[i] = 10; 224 | if (n == 0) { 225 | assert(s(10) == -1); 226 | } else { 227 | assert(0 <= s(10) && s(10) < n); 228 | } 229 | assert(s(5) == -1); 230 | assert(s(15) == -1); 231 | } 232 | } 233 | 234 | /* Timing */ 235 | 236 | int p[MAXN]; 237 | 238 | void scramble(int n) 239 | { int i, j; 240 | DataType t; 241 | for (i = n-1; i > 0; i--) { 242 | j = (RAND_MAX*rand() + rand()) % (i + 1); 243 | t = p[i]; p[i] = p[j]; p[j] = t; 244 | } 245 | } 246 | 247 | void timedriver() 248 | { int i, algnum, numtests, test, start, clicks; 249 | while (scanf("%d %d %d", &algnum, &n, &numtests) != EOF) { 250 | for (i = 0; i < n; i++) 251 | x[i] = i; 252 | for (i = 0; i < n; i++) 253 | p[i] = i; 254 | scramble(n); 255 | start = clock(); 256 | for (test = 0; test < numtests; test++) { 257 | for (i = 0; i < n; i++) { 258 | switch (algnum) { 259 | case 1: assert(binarysearch1(p[i]) == p[i]); break; 260 | case 2: assert(binarysearch2(p[i]) == p[i]); break; 261 | case 3: assert(binarysearch3(p[i]) == p[i]); break; 262 | case 4: assert(binarysearch4(p[i]) == p[i]); break; 263 | case 9: assert(binarysearch9(p[i]) == p[i]); break; 264 | case 21: assert(seqsearch1(p[i]) == p[i]); break; 265 | case 22: assert(seqsearch2(p[i]) == p[i]); break; 266 | case 23: assert(seqsearch3(p[i]) == p[i]); break; 267 | } 268 | } 269 | } 270 | clicks = clock() - start; 271 | printf("%d\t%d\t%d\t%d\t%g\n", 272 | algnum, n, numtests, clicks, 273 | 1e9*clicks/((float) CLOCKS_PER_SEC*n*numtests)); 274 | } 275 | } 276 | 277 | /* Main */ 278 | 279 | int main() 280 | { /* probe1(); */ 281 | /* test(25); */ 282 | timedriver(); 283 | return 0; 284 | } 285 | -------------------------------------------------------------------------------- /part-2/column-7/timemod0.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* timemod0.c -- Simple experiments on C run time costs */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { int i, n, ia, ib, ic; 12 | float fa, fb, fc; 13 | n = 1000000000; /* run time in secs gives nanosecs/loop */ 14 | ia = ib = ic = 9; 15 | fa = fb = 9.0; 16 | for (i = 0; i < n; i++) { 17 | /* null loop 19.1 */ 18 | /* ia = ib + ic; 17.7 */ 19 | /* ia = ib - ic; 17.6 */ 20 | /* ia = ib * ic; 17.7 */ 21 | /* ia = ib % ic; 98.3 */ 22 | /* ia = ib / ic; 98.3 */ 23 | /* ia = rand(); 41.5 */ 24 | /* fa = sqrt(fb); 184 */ 25 | /* free(malloc(8)); 2400 */ 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /part-2/column-8/maxsum.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* maxsum.c -- time algs for maximum-sum subsequence 5 | * Input: algnum, n 6 | * Output: algnum, n, answer, ticks, secs 7 | * See main for algnum codes 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #define MAXN 10000000 15 | int n; 16 | float x[MAXN]; 17 | 18 | void sprinkle() /* Fill x[n] with reals uniform on [-1,1] */ 19 | { int i; 20 | for (i = 0; i < n; i++) 21 | x[i] = 1 - 2*( (float) rand()/RAND_MAX); 22 | } 23 | 24 | float alg1() 25 | { int i, j, k; 26 | float sum, maxsofar = 0; 27 | for (i = 0; i < n; i++) 28 | for (j = i; j < n; j++) { 29 | sum = 0; 30 | for (k = i; k <= j; k++) 31 | sum += x[k]; 32 | if (sum > maxsofar) 33 | maxsofar = sum; 34 | } 35 | return maxsofar; 36 | } 37 | 38 | float alg2() 39 | { int i, j; 40 | float sum, maxsofar = 0; 41 | for (i = 0; i < n; i++) { 42 | sum = 0; 43 | for (j = i; j < n; j++) { 44 | sum += x[j]; 45 | if (sum > maxsofar) 46 | maxsofar = sum; 47 | } 48 | } 49 | return maxsofar; 50 | } 51 | 52 | float cumvec[MAXN+1]; 53 | 54 | float alg2b() 55 | { int i, j; 56 | float *cumarr, sum, maxsofar = 0; 57 | cumarr = cumvec+1; /* to access cumarr[-1] */ 58 | cumarr[-1] = 0; 59 | for (i = 0; i < n; i++) 60 | cumarr[i] = cumarr[i-1] + x[i]; 61 | for (i = 0; i < n; i++) { 62 | for (j = i; j < n; j++) { 63 | sum = cumarr[j] - cumarr[i-1]; 64 | if (sum > maxsofar) 65 | maxsofar = sum; 66 | } 67 | } 68 | return maxsofar; 69 | } 70 | 71 | /* MS VC++ has a max macro, and therefore a perf bug */ 72 | 73 | #ifdef max 74 | #undef max 75 | #endif 76 | 77 | 78 | #define maxmac(a, b) ((a) > (b) ? (a) : (b) ) 79 | 80 | float maxfun(float a, float b) 81 | { return a > b ? a : b; 82 | } 83 | 84 | #define max(a, b) maxfun(a, b) 85 | 86 | float recmax(int l, int u) 87 | { int i, m; 88 | float lmax, rmax, sum; 89 | if (l > u) /* zero elements */ 90 | return 0; 91 | if (l == u) /* one element */ 92 | return max(0, x[l]); 93 | m = (l+u) / 2; 94 | /* find max crossing to left */ 95 | lmax = sum = 0; 96 | for (i = m; i >= l; i--) { 97 | sum += x[i]; 98 | if (sum > lmax) 99 | lmax = sum; 100 | } 101 | /* find max crossing to right */ 102 | rmax = sum = 0; 103 | for (i = m+1; i <= u; i++) { 104 | sum += x[i]; 105 | if (sum > rmax) 106 | rmax = sum; 107 | } 108 | return max(lmax + rmax, 109 | max(recmax(l, m), recmax(m+1, u))); 110 | } 111 | 112 | float alg3() 113 | { return recmax(0, n-1); 114 | } 115 | 116 | float alg4() 117 | { int i; 118 | float maxsofar = 0, maxendinghere = 0; 119 | for (i = 0; i < n; i++) { 120 | maxendinghere += x[i]; 121 | if (maxendinghere < 0) 122 | maxendinghere = 0; 123 | if (maxsofar < maxendinghere) 124 | maxsofar = maxendinghere; 125 | } 126 | return maxsofar; 127 | } 128 | 129 | float alg4b() 130 | { int i; 131 | float maxsofar = 0, maxendinghere = 0; 132 | for (i = 0; i < n; i++) { 133 | maxendinghere += x[i]; 134 | maxendinghere = maxmac(maxendinghere, 0); 135 | maxsofar = maxmac(maxsofar, maxendinghere); 136 | } 137 | return maxsofar; 138 | } 139 | 140 | float alg4c() 141 | { int i; 142 | float maxsofar = 0, maxendinghere = 0; 143 | for (i = 0; i < n; i++) { 144 | maxendinghere += x[i]; 145 | maxendinghere = maxfun(maxendinghere, 0); 146 | maxsofar = maxfun(maxsofar, maxendinghere); 147 | } 148 | return maxsofar; 149 | } 150 | 151 | int main() 152 | { int algnum, start, clicks; 153 | float thisans; 154 | 155 | while (scanf("%d %d", &algnum, &n) != EOF) { 156 | sprinkle(); 157 | start = clock(); 158 | thisans = -1; 159 | switch (algnum) { 160 | case 1: thisans = alg1(); break; 161 | case 2: thisans = alg2(); break; 162 | case 22: thisans = alg2b(); break; 163 | case 3: thisans = alg3(); break; 164 | case 4: thisans = alg4(); break; 165 | case 42: thisans = alg4b(); break; 166 | case 43: thisans = alg4c(); break; 167 | default: break; 168 | } 169 | clicks = clock()-start; 170 | printf("%d\t%d\t%f\t%d\t%f\n", algnum, n, thisans, 171 | clicks, clicks / (float) CLOCKS_PER_SEC); 172 | if (alg4() != thisans) 173 | printf(" maxsum error: mismatch with alg4: %f\n", alg4()); 174 | } 175 | return 0; 176 | } 177 | -------------------------------------------------------------------------------- /part-2/column-9/genbins.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* genbins.c -- generate random numbers with bins */ 5 | 6 | /* If NODESIZE is 8, this program uses the special-case malloc. 7 | Change NODESIZE to 0 to use the system malloc. 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #define NODESIZE 8 14 | #define NODEGROUP 1000 15 | int nodesleft = 0; 16 | char *freenode; 17 | 18 | void *pmalloc(int size) 19 | { void *p; 20 | if (size != NODESIZE) 21 | return malloc(size); 22 | if (nodesleft == 0) { 23 | freenode = malloc(NODEGROUP*NODESIZE); 24 | nodesleft = NODEGROUP; 25 | } 26 | nodesleft--; 27 | p = (void *) freenode; 28 | freenode += NODESIZE; 29 | return p; 30 | } 31 | 32 | struct node { 33 | int val; 34 | struct node *next; 35 | }; 36 | 37 | struct node **bin, *sentinel; 38 | int bins, bincnt, maxval; 39 | 40 | void initbins(int maxelms, int pmaxval) 41 | { int i; 42 | bins = maxelms; 43 | maxval = pmaxval; 44 | bin = pmalloc(bins*sizeof(struct node *)); 45 | sentinel = pmalloc(sizeof(struct node)); 46 | sentinel->val = maxval; 47 | for (i = 0; i < bins; i++) 48 | bin[i] = sentinel; 49 | bincnt = 0; 50 | } 51 | 52 | struct node *rinsert(struct node *p, int t) 53 | { if (p->val < t) { 54 | p->next = rinsert(p->next, t); 55 | } else if (p->val > t) { 56 | struct node *q = pmalloc(sizeof(struct node)); 57 | q->val = t; 58 | q->next = p; 59 | p = q; 60 | bincnt++; 61 | } 62 | return p; 63 | } 64 | 65 | void insert(int t) 66 | { int i; 67 | i = t / (1 + maxval/bins); 68 | i = t / (1 + maxval/bins); 69 | bin[i] = rinsert(bin[i], t); 70 | } 71 | 72 | void report() 73 | { int i, j = 0; 74 | struct node *p; 75 | for (i = 0; i < bins; i++) 76 | for (p = bin[i]; p != sentinel; p = p->next) 77 | /* printf("%d\n", p->val) */; 78 | /* Uncomment for testing, comment for profiling */ 79 | } 80 | 81 | int bigrand() 82 | { return RAND_MAX*rand() + rand(); 83 | } 84 | 85 | int main(int argc, char *argv[]) 86 | { int m = atoi(argv[1]); 87 | int n = atoi(argv[2]); 88 | initbins(m, n); 89 | while (bincnt < m) { 90 | insert(bigrand() % n); 91 | } 92 | report(); 93 | return 0; 94 | } -------------------------------------------------------------------------------- /part-2/column-9/macfun.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* macfun.c -- time macro and function implementations of max 5 | * Input: a sequence of (alg num, n) pairs. 6 | * Output: for each test, (alg num, n, ans, ticks, secs) 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define MAXN 1000000 14 | float x[MAXN]; 15 | 16 | 17 | /* arrmax1 -- max is a macro */ 18 | 19 | #define max1(a, b) ((a) > (b) ? (a) : (b)) 20 | 21 | float arrmax1(int n) 22 | { if (n == 1) 23 | return x[0]; 24 | else 25 | return max1(x[n-1], arrmax1(n-1)); 26 | } 27 | 28 | 29 | /* arrmax2 -- max is a function */ 30 | 31 | float max2(float a, float b) 32 | { return a > b ? a : b; 33 | } 34 | 35 | float arrmax2(int n) 36 | { if (n == 1) 37 | return x[0]; 38 | else 39 | return max2(x[n-1], arrmax2(n-1)); 40 | } 41 | 42 | 43 | /* arrmax3 -- MS VC++ stdlib defines max as a macro */ 44 | 45 | #ifndef max 46 | #define max(a, b) max2(a, b) 47 | #endif 48 | 49 | float arrmax3(int n) 50 | { if (n == 1) 51 | return x[0]; 52 | else 53 | return max(x[n-1], arrmax3(n-1)); 54 | } 55 | 56 | 57 | int main() 58 | { int algnum, i, n, start, clicks; 59 | float thisans; 60 | 61 | for (i = 0; i < MAXN; i++) 62 | x[i] = MAXN-i; 63 | while (scanf("%d %d", &algnum, &n) != EOF) { 64 | start = clock(); 65 | thisans = -1; 66 | switch (algnum) { 67 | case 1: thisans = arrmax1(n); break; 68 | case 2: thisans = arrmax2(n); break; 69 | case 3: thisans = arrmax3(n); break; 70 | default: break; 71 | } 72 | clicks = clock()-start; 73 | printf("%d\t%d\t%g\t%d\t%g\n", algnum, n, thisans, 74 | clicks, clicks / (float) CLOCKS_PER_SEC); 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /part-2/column-9/maxsum.c: -------------------------------------------------------------------------------- 1 | ../column-8/maxsum.c -------------------------------------------------------------------------------- /part-2/column-9/rotate.c: -------------------------------------------------------------------------------- 1 | ../../part-1/column-2/rotate.c -------------------------------------------------------------------------------- /part-2/column-9/search.c: -------------------------------------------------------------------------------- 1 | ../../part-1/column-5/search.c -------------------------------------------------------------------------------- /part-3/column-11/SortAnim.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999 Lucent Technologies 2 | // From 'Programming Pearls' by Jon Bentley 3 | 4 | // SortAnim.java -- Animate sorting algorithms 5 | 6 | import java.applet.*; 7 | import java.awt.*; 8 | import java.util.Date; 9 | 10 | public class SortAnim extends Applet { 11 | // Screen Elements 12 | private TextField n_text; 13 | private Choice dist_choices; 14 | private Choice alg_choices; 15 | private Button run_button; 16 | private Label msg_label; 17 | private Color draw_color = Color.black; 18 | private Color back_color = Color.white; 19 | 20 | // SORTING DATA AND ALGS 21 | 22 | static private final int MAXN = 10000; 23 | static private int n=100; 24 | static private float a[] = new float[MAXN]; 25 | 26 | // Sorting: Generate Inputs 27 | static private final int GEN_RAND = 0; 28 | static private final int GEN_ASCEND = 1; 29 | static private final int GEN_DESCEND = 2; 30 | static private int gen_num = GEN_RAND; 31 | 32 | private void genarray() 33 | { for (int i = 0; i < n; i++) { 34 | switch(gen_num) { 35 | case GEN_RAND: a[i] = (float) Math.random(); break; 36 | case GEN_ASCEND: a[i] = ((float) i)/n; break; 37 | case GEN_DESCEND: a[i] = (float) (1.0 - ((float) i)/n); break; 38 | } 39 | } 40 | } 41 | 42 | // Sorting: Supporting Algs 43 | private void baseswap(int i, int j) 44 | { float t = a[i]; 45 | a[i] = a[j]; 46 | a[j] = t; 47 | } 48 | 49 | // Sorting: Animation Support 50 | static private final int MINX = 20, MAXX = 580; 51 | static private final int MINY = 50, MAXY = 380; 52 | static private float factorx, factory; 53 | static private boolean wantanim = true; 54 | 55 | private void initdisplay() 56 | { Graphics g = this.getGraphics(); 57 | Rectangle r = this.bounds(); 58 | g.setColor(back_color); 59 | g.fillRect(r.x, r.y, r.width, r.height); 60 | factorx = ((float) MAXX-MINX) / n; 61 | factory = ((float) MAXY-MINY); 62 | } 63 | 64 | private void draw(int i, Color c) 65 | { Graphics g = this.getGraphics(); // BETTER WAY? 66 | int d = 4; 67 | int px = (int) (MINX + factorx*i); 68 | int py = MAXY - (int)(factory*a[i]); 69 | g.setColor(c); 70 | g.drawOval(px, py, d, d); 71 | } 72 | 73 | private void swap(int i, int j) 74 | { if (wantanim) { 75 | draw(i, back_color); 76 | draw(j, back_color); 77 | } 78 | baseswap(i, j); 79 | if (wantanim) { 80 | draw(i, draw_color); 81 | draw(j, draw_color); 82 | } 83 | } 84 | 85 | // Sorting Algs 86 | private void isort() 87 | { for (int i = 1; i < n; i++) 88 | for (int j = i; j > 0 && a[j-1] > a[j]; j--) 89 | swap(j-1, j); 90 | } 91 | 92 | private void ssort() 93 | { for (int i = 0; i < n-1; i++) 94 | for (int j = i; j < n; j++) 95 | if (a[j] < a[i]) 96 | swap(i, j); 97 | } 98 | 99 | private void shellsort() 100 | { int i, j, h; 101 | for (h = 1; h < n; h = 3*h + 1) 102 | ; 103 | for (;;) { 104 | h /= 3; 105 | if (h < 1) break; 106 | for (i = h; i < n; i++) { 107 | for (j = i; j >= h; j -= h) { 108 | if (a[j-h] < a[j]) break; 109 | swap(j-h, j); 110 | } 111 | } 112 | } 113 | } 114 | 115 | private void siftdown(int l, int u) 116 | { int i, c; 117 | i = l; 118 | for (;;) { 119 | c = 2*i; 120 | if (c > u) 121 | break; 122 | if (c+1 <= u && a[c+1] > a[c]) 123 | c++; 124 | if (a[i] >= a[c]) 125 | break; 126 | swap(i, c); 127 | i = c; 128 | } 129 | } 130 | 131 | private void heapsort() // BEWARE!!! Sorts x[1..n-1] 132 | { int i; 133 | for (i = n/2; i > 0; i--) 134 | siftdown(i, n-1); 135 | for (i = n-1; i >= 2; i--) { 136 | swap(1, i); 137 | siftdown(1, i-1); 138 | } 139 | } 140 | 141 | private void qsort(int l, int u) 142 | { if (l >= u) 143 | return; 144 | int m = l; 145 | for (int i = l+1; i <= u; i++) 146 | if (a[i] < a[l]) 147 | swap(++m, i); 148 | swap(l, m); 149 | qsort(l, m-1); 150 | qsort(m+1, u); 151 | } 152 | 153 | void qsort2(int l, int u) 154 | { if (l >= u) 155 | return; 156 | int i = l; 157 | int j = u+1; 158 | for (;;) { 159 | do i++; while (i <= u && a[i] < a[l]); 160 | do j--; while (a[j] > a[l]); 161 | if (i > j) 162 | break; 163 | swap(i, j); 164 | } 165 | swap(l, j); 166 | qsort2(l, j-1); 167 | qsort2(j+1, u); 168 | } 169 | 170 | // Drive Sort 171 | static private final int ALG_ISORT = 0; 172 | static private final int ALG_SELSORT = 1; 173 | static private final int ALG_SHELLSORT = 2; 174 | static private final int ALG_HSORT = 3; 175 | static private final int ALG_QSORT = 4; 176 | static private final int ALG_QSORT2 = 5; 177 | static private int alg_num = ALG_ISORT; 178 | 179 | private void dosort() 180 | { switch(alg_num) { 181 | case ALG_ISORT: isort(); break; 182 | case ALG_SELSORT: ssort(); break; 183 | case ALG_SHELLSORT: shellsort(); break; 184 | case ALG_HSORT: heapsort(); break; 185 | case ALG_QSORT: qsort(0, n-1); break; 186 | case ALG_QSORT2: qsort2(0, n-1); break; 187 | } 188 | } 189 | 190 | private void runanim() 191 | { n = Integer.parseInt(n_text.getText()); 192 | if (n < 1 || n > MAXN) { 193 | n = 50; 194 | n_text.setText("" + n); 195 | } 196 | initdisplay(); 197 | msg_label.setText("Running"); 198 | genarray(); 199 | for (int i = 0; i < n; i++) 200 | draw(i, draw_color); 201 | Date timer = new Date(); 202 | long start = timer.getTime(); 203 | dosort(); 204 | timer = new Date(); 205 | long msecs = timer.getTime() - start; 206 | msg_label.setText("Msecs: " + msecs); 207 | if (! wantanim) // Draw results over input 208 | for (int i = 0; i < n; i++) 209 | draw(i, draw_color); 210 | } 211 | 212 | // GUI FUNCTIONS 213 | public void init() { 214 | this.setBackground(back_color); 215 | 216 | // TextField for n (problem size) 217 | n_text = new TextField(5); 218 | this.add(new Label("n:")); 219 | this.add(n_text); 220 | n_text.setText("" + n); 221 | 222 | // Choice of Starting distributions 223 | dist_choices = new Choice(); 224 | dist_choices.addItem("Random"); 225 | dist_choices.addItem("Ascending"); 226 | dist_choices.addItem("Descending"); 227 | this.add(new Label("Input:")); 228 | this.add(dist_choices); 229 | 230 | // Choice of Sort Algorithms 231 | alg_choices = new Choice(); 232 | alg_choices.addItem("Insertion Sort"); 233 | alg_choices.addItem("Selection Sort"); 234 | alg_choices.addItem("Shell Sort"); 235 | alg_choices.addItem("Heap Sort"); 236 | alg_choices.addItem("Quicksort"); 237 | alg_choices.addItem("2-way Quicksort"); 238 | this.add(new Label("Algorithm:")); 239 | this.add(alg_choices); 240 | 241 | // Run Button 242 | run_button = new Button("Run"); 243 | this.add(run_button); 244 | 245 | // Message Label 246 | msg_label = new Label(" "); 247 | this.add(msg_label); 248 | } 249 | 250 | public boolean action(Event event, Object arg) { 251 | if (event.target == dist_choices) { 252 | if (arg.equals("Random")) gen_num = GEN_RAND; 253 | else if (arg.equals("Ascending")) gen_num = GEN_ASCEND; 254 | else if (arg.equals("Descending")) gen_num = GEN_DESCEND; 255 | return true; 256 | } else if (event.target == alg_choices) { 257 | if (arg.equals("Insertion Sort")) alg_num = ALG_ISORT; 258 | else if (arg.equals("Selection Sort")) alg_num = ALG_SELSORT; 259 | else if (arg.equals("Shell Sort")) alg_num = ALG_SHELLSORT; 260 | else if (arg.equals("Heap Sort")) alg_num = ALG_HSORT; 261 | else if (arg.equals("Quicksort")) alg_num = ALG_QSORT; 262 | else if (arg.equals("2-way Quicksort")) alg_num = ALG_QSORT2; 263 | return true; 264 | } else if (event.target == run_button) { 265 | runanim(); 266 | return true; 267 | } else 268 | return super.action(event, arg); 269 | } 270 | } -------------------------------------------------------------------------------- /part-3/column-11/sort.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* sort.cpp -- test and time sorting algorithms 5 | Input lines: algnum n mod 6 | Output lines: algnum n mod clicks nanosecs_per_elem 7 | This is predominantly a C program; the only use of C++ 8 | sort function immediately below the include line. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // To change from C++ back to C, remove the following two lines 16 | // and the call to sort in main 17 | #include 18 | using namespace std; 19 | 20 | /* Data and supporting functions */ 21 | 22 | #define MAXN 10000000 23 | 24 | typedef int DType; 25 | 26 | DType realx[MAXN]; 27 | int *x = realx; /* allow x to shift for heaps */ 28 | int n; 29 | 30 | void swap(int i, int j) 31 | { DType t = x[i]; 32 | x[i] = x[j]; 33 | x[j] = t; 34 | } 35 | 36 | int randint(int l, int u) 37 | { return l + (RAND_MAX*rand() + rand()) % (u-l+1); 38 | } 39 | 40 | /* LIBRARY QSORT */ 41 | 42 | int intcomp(int *x, int *y) 43 | { return *x - *y; 44 | } 45 | 46 | /* INSERTION SORTS */ 47 | 48 | /* Simplest insertion sort */ 49 | void isort1() 50 | { int i, j; 51 | for (i = 1; i < n; i++) 52 | for (j = i; j > 0 && x[j-1] > x[j]; j--) 53 | swap(j-1, j); 54 | } 55 | 56 | /* Write swap function inline */ 57 | void isort2() 58 | { int i, j; 59 | DType t; 60 | for (i = 1; i < n; i++) 61 | for (j = i; j > 0 && x[j-1] > x[j]; j--) { 62 | t = x[j]; 63 | x[j] = x[j-1]; 64 | x[j-1] = t; 65 | } 66 | } 67 | 68 | /* Move assignments to and from t out of loop */ 69 | void isort3() 70 | { int i, j; 71 | DType t; 72 | for (i = 1; i < n; i++) { 73 | t = x[i]; 74 | for (j = i; j > 0 && x[j-1] > t; j--) 75 | x[j] = x[j-1]; 76 | x[j] = t; 77 | } 78 | } 79 | 80 | /* QUICKSORTS */ 81 | 82 | /* Simplest version, Lomuto partitioning */ 83 | void qsort1(int l, int u) 84 | { int i, m; 85 | if (l >= u) 86 | return; 87 | m = l; 88 | for (i = l+1; i <= u; i++) 89 | if (x[i] < x[l]) 90 | swap(++m, i); 91 | swap(l, m); 92 | qsort1(l, m-1); 93 | qsort1(m+1, u); 94 | } 95 | 96 | /* Sedgewick's version of Lomuto, with sentinel */ 97 | void qsort2(int l, int u) 98 | { int i, m; 99 | if (l >= u) 100 | return; 101 | m = i = u+1; 102 | do { 103 | do i--; while (x[i] < x[l]); 104 | swap(--m, i); 105 | } while (i > l); 106 | qsort2(l, m-1); 107 | qsort2(m+1, u); 108 | } 109 | 110 | /* Two-way partitioning */ 111 | void qsort3(int l, int u) 112 | { int i, j; 113 | DType t; 114 | if (l >= u) 115 | return; 116 | t = x[l]; 117 | i = l; 118 | j = u+1; 119 | for (;;) { 120 | do i++; while (i <= u && x[i] < t); 121 | do j--; while (x[j] > t); 122 | if (i > j) 123 | break; 124 | swap(i, j); 125 | } 126 | swap(l, j); 127 | qsort3(l, j-1); 128 | qsort3(j+1, u); 129 | } 130 | 131 | /* qsort3 + randomization + isort small subarrays + swap inline */ 132 | int cutoff = 50; 133 | void qsort4(int l, int u) 134 | { int i, j; 135 | DType t, temp; 136 | if (u - l < cutoff) 137 | return; 138 | swap(l, randint(l, u)); 139 | t = x[l]; 140 | i = l; 141 | j = u+1; 142 | for (;;) { 143 | do i++; while (i <= u && x[i] < t); 144 | do j--; while (x[j] > t); 145 | if (i > j) 146 | break; 147 | temp = x[i]; x[i] = x[j]; x[j] = temp; 148 | } 149 | swap(l, j); 150 | qsort4(l, j-1); 151 | qsort4(j+1, u); 152 | } 153 | 154 | /* selection */ 155 | 156 | void select1(int l, int u, int k) 157 | { int i, j; 158 | DType t, temp; 159 | if (l >= u) 160 | return; 161 | swap(l, randint(l, u)); 162 | t = x[l]; 163 | i = l; 164 | j = u+1; 165 | for (;;) { 166 | do i++; while (i <= u && x[i] < t); 167 | do j--; while (x[j] > t); 168 | if (i > j) 169 | break; 170 | temp = x[i]; x[i] = x[j]; x[j] = temp; 171 | } 172 | swap(l, j); 173 | if (j < k) 174 | select1(j+1, u, k); 175 | else if (j > k) 176 | select1(l, j-1, k); 177 | } 178 | 179 | /* HEAP SORTS */ 180 | 181 | void siftup(int u) 182 | { int i, p; 183 | i = u; 184 | for (;;) { 185 | if (i == 1) 186 | break; 187 | p = i / 2; 188 | if (x[p] >= x[i]) 189 | break; 190 | swap(p, i); 191 | i = p; 192 | } 193 | } 194 | 195 | void siftdown1(int l, int u) 196 | { int i, c; 197 | i = l; 198 | for (;;) { 199 | c = 2*i; 200 | if (c > u) 201 | break; 202 | if (c+1 <= u && x[c+1] > x[c]) 203 | c++; 204 | if (x[i] > x[c]) 205 | break; 206 | swap(i, c); 207 | i = c; 208 | } 209 | } 210 | 211 | void siftdown1b(int l, int u) /* More C-ish version of 1 */ 212 | { int i, c; 213 | for (i = l; (c = 2*i) <= u; i = c) { 214 | if (c+1 <= u && x[c+1] > x[c]) 215 | c++; 216 | if (x[i] > x[c]) 217 | break; 218 | swap(i, c); 219 | } 220 | } 221 | 222 | void hsort1() 223 | { int i; 224 | x--; 225 | for (i = 2; i <= n; i++) 226 | siftup(i); 227 | for (i = n; i >= 2; i--) { 228 | swap(1, i); 229 | siftdown1(1, i-1); 230 | } 231 | x++; 232 | } 233 | 234 | void hsort2() 235 | { int i; 236 | x--; 237 | for (i = n/2; i >= 1; i--) 238 | siftdown1(i, n); 239 | for (i = n; i >= 2; i--) { 240 | swap(1, i); 241 | siftdown1(1, i-1); 242 | } 243 | x++; 244 | } 245 | 246 | void siftdown3(int l, int u) /* push to bottom, then back up */ 247 | { int i, c, p; 248 | i = l; 249 | for (;;) { 250 | c = 2*i; 251 | if (c > u) 252 | break; 253 | if (c+1 <= u && x[c+1] > x[c]) 254 | c++; 255 | swap(i, c); 256 | i = c; 257 | } 258 | for (;;) { 259 | p = i/2; 260 | if (p < l) 261 | break; 262 | if (x[p] > x[i]) 263 | break; 264 | swap(p, i); 265 | i = p; 266 | } 267 | } 268 | 269 | void hsort3() 270 | { int i; 271 | x--; 272 | for (i = n/2; i >= 1; i--) 273 | siftdown3(i, n); 274 | for (i = n; i >= 2; i--) { 275 | swap(1, i); 276 | siftdown3(1, i-1); 277 | } 278 | x++; 279 | } 280 | 281 | void siftdown4(int l, int u) /* replace swap with assignments */ 282 | { int i, c, p; 283 | DType t; 284 | t = x[l]; 285 | i = l; 286 | for (;;) { 287 | c = 2*i; 288 | if (c > u) 289 | break; 290 | if (c+1 <= u && x[c+1] > x[c]) 291 | c++; 292 | x[i] = x[c]; 293 | i = c; 294 | } 295 | x[i] = t; 296 | for (;;) { 297 | p = i/2; 298 | if (p < l) 299 | break; 300 | if (x[p] > x[i]) 301 | break; 302 | swap(p, i); 303 | i = p; 304 | } 305 | } 306 | 307 | void hsort4() 308 | { int i; 309 | x--; 310 | for (i = n/2; i >= 1; i--) 311 | siftdown4(i, n); 312 | for (i = n; i >= 2; i--) { 313 | swap(1, i); 314 | siftdown4(1, i-1); 315 | } 316 | x++; 317 | } 318 | 319 | 320 | /* Other Sorts -- Exercises in Column 11 */ 321 | 322 | void selsort() /* Selection sort */ 323 | { int i, j; 324 | for (i = 0; i < n-1; i++) 325 | for (j = i; j < n; j++) 326 | if (x[j] < x[i]) 327 | swap(i, j); 328 | } 329 | 330 | void shellsort() 331 | { int i, j, h; 332 | for (h = 1; h < n; h = 3*h + 1) 333 | ; 334 | for (;;) { 335 | h /= 3; 336 | if (h < 1) break; 337 | for (i = h; i < n; i++) { 338 | for (j = i; j >= h; j -= h) { 339 | if (x[j-h] < x[j]) break; 340 | swap(j-h, j); 341 | } 342 | } 343 | } 344 | } 345 | 346 | 347 | 348 | /* SCAFFOLDING */ 349 | 350 | /* Timing */ 351 | 352 | void timedriver() 353 | { int i, k, algnum, mod, start, clicks; 354 | while (scanf("%d %d %d", &algnum, &n, &mod) != EOF) { 355 | if (mod <= 0) 356 | mod = 10*n; 357 | for (i = 0; i < n; i++) 358 | x[i] = randint(0, mod-1); 359 | k = n/2; 360 | start = clock(); 361 | switch (algnum) { 362 | case 11: qsort(x, n, sizeof(int), (int (__cdecl *)(const void *,const void *)) intcomp); break; 363 | case 12: sort(x, x+n); break; 364 | case 21: isort1(); break; 365 | case 22: isort2(); break; 366 | case 23: isort3(); break; 367 | case 31: qsort1(0, n-1); break; 368 | case 32: qsort2(0, n-1); break; 369 | case 33: qsort3(0, n-1); break; 370 | case 34: qsort4(0, n-1); isort3(); break; 371 | case 41: select1(0, n-1, k); break; 372 | case 51: hsort1(); break; 373 | case 52: hsort2(); break; 374 | case 53: hsort3(); break; 375 | case 54: hsort4(); break; 376 | case 61: selsort(); break; 377 | case 62: shellsort(); break; 378 | } 379 | clicks = clock() - start; 380 | if (algnum == 41) { /* Test selection */ 381 | for (i = 0; i < k; i++) 382 | if (x[i] > x[k]) 383 | printf(" SELECT BUG i=%d\n", i); 384 | for (i = k+1; i < n; i++) 385 | if (x[i] < x[k]) 386 | printf(" SELECT BUG i=%d\n", i); 387 | } else { /* Test sort */ 388 | for (i = 0; i < n-1; i++) 389 | if (x[i] > x[i+1]) 390 | printf(" SORT BUG i=%d\n", i); 391 | } 392 | printf("%d\t%d\t%d\t%d\t%g\n", 393 | algnum, n, mod, clicks, 394 | 1e9*clicks/((float) CLOCKS_PER_SEC*n)); 395 | } 396 | } 397 | 398 | /* Main */ 399 | 400 | int main() 401 | { timedriver(); 402 | return 0; 403 | } 404 | -------------------------------------------------------------------------------- /part-3/column-12/sortedrand.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* sortedrand.cpp -- output m sorted random ints in U[0,n) */ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int bigrand() 12 | { return RAND_MAX*rand() + rand(); 13 | } 14 | 15 | int randint(int l, int u) 16 | { return l + bigrand() % (u-l+1); 17 | } 18 | 19 | void genknuth(int m, int n) 20 | { for (int i = 0; i < n; i++) 21 | /* select m of remaining n-i */ 22 | if ((bigrand() % (n-i)) < m) { 23 | cout << i << "\n"; 24 | m--; 25 | } 26 | } 27 | 28 | void gensets(int m, int n) 29 | { set S; 30 | set::iterator i; 31 | while (S.size() < m) { 32 | int t = bigrand() % n; 33 | S.insert(t); 34 | } 35 | for (i = S.begin(); i != S.end(); ++i) 36 | cout << *i << "\n"; 37 | } 38 | 39 | void genshuf(int m, int n) 40 | { int i, j; 41 | int *x = new int[n]; 42 | for (i = 0; i < n; i++) 43 | x[i] = i; 44 | for (i = 0; i < m; i++) { 45 | j = randint(i, n-1); 46 | int t = x[i]; x[i] = x[j]; x[j] = t; 47 | } 48 | sort(x, x+m); 49 | for (i = 0; i < m; i++) 50 | cout << x[i] << "\n"; 51 | } 52 | 53 | void genfloyd(int m, int n) 54 | { set S; 55 | set::iterator i; 56 | for (int j = n-m; j < n; j++) { 57 | int t = bigrand() % (j+1); 58 | if (S.find(t) == S.end()) 59 | S.insert(t); // t not in S 60 | else 61 | S.insert(j); // t in S 62 | } 63 | for (i = S.begin(); i != S.end(); ++i) 64 | cout << *i << "\n"; 65 | } 66 | 67 | int main(int argc, char *argv[]) 68 | { int m = atoi(argv[1]); 69 | int n = atoi(argv[2]); 70 | genknuth(m, n); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /part-3/column-13/genbins.c: -------------------------------------------------------------------------------- 1 | ../../part-2/column-9/genbins.c -------------------------------------------------------------------------------- /part-3/column-13/sets.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* sets.cpp -- exercise set implementations on random numbers */ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | 11 | class IntSetSTL { 12 | private: 13 | set S; 14 | public: 15 | IntSetSTL(int maxelements, int maxval) { } 16 | int size() { return S.size(); } 17 | void insert(int t) { S.insert(t);} 18 | void report(int *v) 19 | { int j = 0; 20 | set::iterator i; 21 | for (i = S.begin(); i != S.end(); ++i) 22 | v[j++] = *i; 23 | } 24 | }; 25 | 26 | 27 | class IntSetBitVec { 28 | private: 29 | enum { BITSPERWORD = 32, SHIFT = 5, MASK = 0x1F }; 30 | int n, hi, *x; 31 | void set(int i) { x[i>>SHIFT] |= (1<<(i & MASK)); } 32 | void clr(int i) { x[i>>SHIFT] &= ~(1<<(i & MASK)); } 33 | int test(int i) { return x[i>>SHIFT] & (1<<(i & MASK)); } 34 | public: 35 | IntSetBitVec(int maxelements, int maxval) 36 | { hi = maxval; 37 | x = new int[1 + hi/BITSPERWORD]; 38 | for (int i = 0; i < hi; i++) 39 | clr(i); 40 | n = 0; 41 | } 42 | int size() { return n; } 43 | void insert(int t) 44 | { if (test(t)) 45 | return; 46 | set(t); 47 | n++; 48 | } 49 | void report(int *v) 50 | { int j=0; 51 | for (int i = 0; i < hi; i++) 52 | if (test(i)) 53 | v[j++] = i; 54 | } 55 | }; 56 | 57 | 58 | class IntSetArr { 59 | private: 60 | int n, *x; 61 | public: 62 | IntSetArr(int maxelements, int maxval) 63 | { x = new int[1 + maxelements]; 64 | n=0; 65 | x[0] = maxval; /* sentinel at x[n] */ 66 | } 67 | int size() { return n; } 68 | void insert(int t) 69 | { int i, j; 70 | for (i = 0; x[i] < t; i++) 71 | ; 72 | if (x[i] == t) 73 | return; 74 | for (j = n; j >= i; j--) 75 | x[j+1] = x[j]; 76 | x[i] = t; 77 | n++; 78 | } 79 | void report(int *v) 80 | { for (int i = 0; i < n; i++) 81 | v[i] = x[i]; 82 | } 83 | }; 84 | 85 | 86 | class IntSetList { 87 | private: 88 | int n; 89 | struct node { 90 | int val; 91 | node *next; 92 | node(int i, node *p) { val = i; next = p; } 93 | }; 94 | node *head, *sentinel; 95 | node *rinsert(node *p, int t) 96 | { if (p->val < t) { 97 | p->next = rinsert(p->next, t); 98 | } else if (p->val > t) { 99 | p = new node(t, p); 100 | n++; 101 | } 102 | return p; 103 | } 104 | public: 105 | IntSetList(int maxelements, int maxval) 106 | { sentinel = head = new node(maxval, 0); 107 | n = 0; 108 | } 109 | int size() { return n; } 110 | void insert(int t) { head = rinsert(head, t); } 111 | void insert2(int t) 112 | { node *p; 113 | if (head->val == t) 114 | return; 115 | if (head->val > t) { 116 | head = new node(t, head); 117 | n++; 118 | return; 119 | } 120 | for (p = head; p->next->val < t; p = p->next) 121 | ; 122 | if (p->next->val == t) 123 | return; 124 | p->next = new node(t, p->next); 125 | n++; 126 | } 127 | void insert3(int t) 128 | { node **p; 129 | for (p = &head; (*p)->val < t; p = &((*p)->next)) 130 | ; 131 | if ((*p)->val == t) 132 | return; 133 | *p = new node(t, *p); 134 | n++; 135 | } 136 | void report(int *v) 137 | { int j = 0; 138 | for (node *p = head; p != sentinel; p = p->next) 139 | v[j++] = p->val; 140 | } 141 | }; 142 | 143 | // Change from new per node to one new at init 144 | // Factor of 2.5 on VC 5.0, 6% on SGI CC 145 | class IntSetList2 { 146 | private: 147 | int n; 148 | struct node { 149 | int val; 150 | node *next; 151 | }; 152 | node *head, *sentinel, *freenode; 153 | public: 154 | IntSetList2(int maxelements, int maxval) 155 | { sentinel = head = new node; 156 | sentinel->val = maxval; 157 | freenode = new node[maxelements]; 158 | n = 0; 159 | } 160 | int size() { return n; } 161 | void insert(int t) 162 | { node **p; 163 | for (p = &head; (*p)->val < t; p = &((*p)->next)) 164 | ; 165 | if ((*p)->val == t) 166 | return; 167 | freenode->val = t; 168 | freenode->next = *p; 169 | *p = freenode++; 170 | n++; 171 | } 172 | void report(int *v) 173 | { int j = 0; 174 | for (node *p = head; p != sentinel; p = p->next) 175 | v[j++] = p->val; 176 | } 177 | }; 178 | 179 | 180 | class IntSetBST { 181 | private: 182 | int n, *v, vn; 183 | struct node { 184 | int val; 185 | node *left, *right; 186 | node(int v) { val = v; left = right = 0; } 187 | }; 188 | node *root; 189 | node *rinsert(node *p, int t) 190 | { if (p == 0) { 191 | p = new node(t); 192 | n++; 193 | } else if (t < p->val) { 194 | p->left = rinsert(p->left, t); 195 | } else if (t > p->val) { 196 | p->right = rinsert(p->right, t); 197 | } // do nothing if p->val == t 198 | return p; 199 | } 200 | void traverse(node *p) 201 | { if (p == 0) 202 | return; 203 | traverse(p->left); 204 | v[vn++] = p->val; 205 | traverse(p->right); 206 | } 207 | public: 208 | IntSetBST(int maxelements, int maxval) { root = 0; n = 0; } 209 | int size() { return n; } 210 | void insert(int t) { root = rinsert(root, t); } 211 | void report(int *x) { v = x; vn = 0; traverse(root); } 212 | }; 213 | 214 | 215 | class IntSetBST2 { 216 | private: 217 | int n, *v, vn; 218 | struct node { 219 | int val; 220 | node *left, *right; 221 | }; 222 | node *root, *freenode, *sentinel; 223 | node *rinsert(node *p, int t) 224 | { if (p == sentinel) { 225 | p = freenode++; 226 | p->val = t; 227 | p->left = p->right = sentinel; 228 | n++; 229 | } else if (t < p->val) { 230 | p->left = rinsert(p->left, t); 231 | } else if (t > p->val) { 232 | p->right = rinsert(p->right, t); 233 | } // do nothing if p->val == t 234 | return p; 235 | } 236 | void traverse(node *p) 237 | { if (p == sentinel) 238 | return; 239 | traverse(p->left); 240 | v[vn++] = p->val; 241 | traverse(p->right); 242 | } 243 | public: 244 | IntSetBST2(int maxelements, int maxval) 245 | { root = sentinel = new node; // 0 if using insert1 246 | n = 0; 247 | freenode = new node[maxelements]; 248 | } 249 | int size() { return n; } 250 | void insert1(int t) { root = rinsert(root, t); } 251 | void insert(int t) 252 | { sentinel->val = t; 253 | node **p = &root; 254 | while ((*p)->val != t) 255 | if (t < (*p)->val) 256 | p = &((*p)->left); 257 | else 258 | p = &((*p)->right); 259 | if (*p == sentinel) { 260 | *p = freenode++; 261 | (*p)->val = t; 262 | (*p)->left = (*p)->right = sentinel; 263 | n++; 264 | } 265 | } 266 | void report(int *x) { v = x; vn = 0; traverse(root); } 267 | }; 268 | 269 | 270 | class IntSetBins { 271 | private: 272 | int n, bins, maxval; 273 | struct node { 274 | int val; 275 | node *next; 276 | node(int v, node *p) { val = v; next = p; } 277 | }; 278 | node **bin, *sentinel; 279 | node *rinsert(node *p, int t) 280 | { if (p->val < t) { 281 | p->next = rinsert(p->next, t); 282 | } else if (p->val > t) { 283 | p = new node(t, p); 284 | n++; 285 | } 286 | return p; 287 | } 288 | public: 289 | IntSetBins(int maxelements, int pmaxval) 290 | { bins = maxelements; 291 | maxval = pmaxval; 292 | bin = new node*[bins]; 293 | sentinel = new node(maxval, 0); 294 | for (int i = 0; i < bins; i++) 295 | bin[i] = sentinel; 296 | n = 0; 297 | } 298 | int size() { return n; } 299 | void insert(int t) 300 | { int i = t / (1 + maxval/bins); // CHECK ! 301 | bin[i] = rinsert(bin[i], t); 302 | } 303 | void report(int *v) 304 | { int j = 0; 305 | for (int i = 0; i < bins; i++) 306 | for (node *p = bin[i]; p != sentinel; p = p->next) 307 | v[j++] = p->val; 308 | } 309 | }; 310 | 311 | 312 | class IntSetBins2 { 313 | private: 314 | int n, bins, maxval; 315 | struct node { 316 | int val; 317 | node *next; 318 | }; 319 | node **bin, *sentinel, *freenode; 320 | node *rinsert(node *p, int t) 321 | { if (p->val < t) { 322 | p->next = rinsert(p->next, t); 323 | } else if (p->val > t) { 324 | freenode->val = t; 325 | freenode->next = p; 326 | p = freenode++; 327 | n++; 328 | } 329 | return p; 330 | } 331 | public: 332 | IntSetBins2(int maxelements, int pmaxval) 333 | { bins = maxelements; 334 | maxval = pmaxval; 335 | freenode = new node[maxelements]; 336 | bin = new node*[bins]; 337 | sentinel = new node; 338 | sentinel->val = maxval; 339 | for (int i = 0; i < bins; i++) 340 | bin[i] = sentinel; 341 | n = 0; 342 | } 343 | int size() { return n; } 344 | void insert1(int t) 345 | { int i = t / (1 + maxval/bins); 346 | bin[i] = rinsert(bin[i], t); 347 | } 348 | void insert(int t) 349 | { node **p; 350 | int i = t / (1 + maxval/bins); 351 | for (p = &bin[i]; (*p)->val < t; p = &((*p)->next)) 352 | ; 353 | if ((*p)->val == t) 354 | return; 355 | freenode->val = t; 356 | freenode->next = *p; 357 | *p = freenode++; 358 | n++; 359 | } 360 | void report(int *v) 361 | { int j = 0; 362 | for (int i = 0; i < bins; i++) 363 | for (node *p = bin[i]; p != sentinel; p = p->next) 364 | v[j++] = p->val; 365 | } 366 | }; 367 | 368 | 369 | // Drivers for the set data structures 370 | 371 | int bigrand() 372 | { return RAND_MAX*rand() + rand(); 373 | } 374 | 375 | int randint(int l, int u) 376 | { return l + bigrand() % (u-l+1); 377 | } 378 | 379 | void gensets(int m, int maxval) 380 | { int *v = new int[m]; 381 | IntSetList S(m, maxval); 382 | while (S.size() < m) 383 | S.insert(bigrand() % maxval); 384 | S.report(v); 385 | // for (int i = 0; i < m; i++) 386 | for (int i = 0; i < 2; i++) 387 | cout << v[i] << "\n"; 388 | } 389 | 390 | void genfloyd(int m, int maxval) 391 | { int *v = new int[m]; 392 | IntSetSTL S(m, maxval); 393 | for (int j = maxval-m; j < maxval; j++) { 394 | int t = bigrand() % (j+1); 395 | int oldsize = S.size(); 396 | S.insert(t); 397 | if (S.size() == oldsize) // t already in S 398 | S.insert(j); 399 | } 400 | S.report(v); 401 | for (int i = 0; i < m; i++) 402 | cout << v[i] << "\n"; 403 | } 404 | 405 | void memaccesstest(int m, int n) 406 | { IntSetList S(m, n); // change among Arr, List and List2 407 | for (int i = 0; i < m; i++) 408 | S.insert(i); 409 | } 410 | 411 | void overheadonly(int m, int n) 412 | { int i, *v = new int[m]; 413 | for (i = 0; i < m; i++) 414 | v[i] = bigrand() % n; 415 | for (i = 0; i < m; i++) 416 | cout << v[i] << "\n"; 417 | } 418 | 419 | int main(int argc, char *argv[]) 420 | { int m = atoi(argv[1]); 421 | int maxval = atoi(argv[2]); 422 | gensets(m, maxval); 423 | // overheadonly(m, n); 424 | // memaccesstest(m, n); 425 | return 0; 426 | } 427 | -------------------------------------------------------------------------------- /part-3/column-14/priqueue.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* priqueue.cpp -- priority queues (using heaps) */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | // define and implement priority queues 10 | 11 | template 12 | class priqueue { 13 | private: 14 | int n, maxsize; 15 | T *x; 16 | void swap(int i, int j) 17 | { T t = x[i]; x[i] = x[j]; x[j] = t; } 18 | public: 19 | priqueue(int m) 20 | { maxsize = m; 21 | x = new T[maxsize+1]; 22 | n = 0; 23 | } 24 | void insert(T t) 25 | { int i, p; 26 | x[++n] = t; 27 | for (i = n; i > 1 && x[p=i/2] > x[i]; i = p) 28 | swap(p, i); 29 | } 30 | T extractmin() 31 | { int i, c; 32 | T t = x[1]; 33 | x[1] = x[n--]; 34 | for (i = 1; (c=2*i) <= n; i = c) { 35 | if (c+1<=n && x[c+1] 48 | void pqsort(T v[], int n) 49 | { priqueue pq(n); 50 | int i; 51 | for (i = 0; i < n; i++) 52 | pq.insert(v[i]); 53 | for (i = 0; i < n; i++) 54 | v[i] = pq.extractmin(); 55 | } 56 | 57 | // main 58 | 59 | int main() 60 | { const int n = 10; 61 | int i, v[n]; 62 | if (0) { // Generate and sort 63 | for (i = 0; i < n; i++) 64 | v[i] = n-i; 65 | pqsort(v, n); 66 | for (i = 0; i < n; i++) 67 | cout << v[i] << "\n"; 68 | } else { // Insert integers; extract with 0 69 | priqueue pq(100); 70 | while (cin >> i) 71 | if (i == 0) 72 | cout << pq.extractmin() << "\n"; 73 | else 74 | pq.insert(i); 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /part-3/column-14/sort.cpp: -------------------------------------------------------------------------------- 1 | ../column-11/sort.cpp -------------------------------------------------------------------------------- /part-3/column-15/longdup.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* longdup.c -- Print longest string duplicated M times */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int pstrcmp(char **p, char **q) 11 | { return strcmp(*p, *q); } 12 | 13 | int comlen(char *p, char *q) 14 | { int i = 0; 15 | while (*p && (*p++ == *q++)) 16 | i++; 17 | return i; 18 | } 19 | 20 | #define M 1 21 | #define MAXN 5000000 22 | char c[MAXN], *a[MAXN]; 23 | 24 | int main() 25 | { int i, ch, n = 0, maxi, maxlen = -1; 26 | while ((ch = getchar()) != EOF) { 27 | a[n] = &c[n]; 28 | c[n++] = ch; 29 | } 30 | c[n] = 0; 31 | qsort(a, n, sizeof(char *), pstrcmp); 32 | for (i = 0; i < n-M; i++) 33 | if (comlen(a[i], a[i+M]) > maxlen) { 34 | maxlen = comlen(a[i], a[i+M]); 35 | maxi = i; 36 | } 37 | printf("%.*s\n", maxlen, a[maxi]); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /part-3/column-15/markov.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* markov.c -- generate random text from input document */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | char inputchars[4300000]; 11 | char *word[800000]; 12 | int nword = 0; 13 | int k = 2; 14 | 15 | int wordncmp(char *p, char* q) 16 | { int n = k; 17 | for ( ; *p == *q; p++, q++) 18 | if (*p == 0 && --n == 0) 19 | return 0; 20 | return *p - *q; 21 | } 22 | 23 | int sortcmp(char **p, char **q) 24 | { return wordncmp(*p, *q); 25 | } 26 | 27 | char *skip(char *p, int n) 28 | { for ( ; n > 0; p++) 29 | if (*p == 0) 30 | n--; 31 | return p; 32 | } 33 | 34 | int main() 35 | { int i, wordsleft = 10000, l, m, u; 36 | char *phrase, *p; 37 | word[0] = inputchars; 38 | while (scanf("%s", word[nword]) != EOF) { 39 | word[nword+1] = word[nword] + strlen(word[nword]) + 1; 40 | nword++; 41 | } 42 | for (i = 0; i < k; i++) 43 | word[nword][i] = 0; 44 | for (i = 0; i < k; i++) 45 | printf("%s\n", word[i]); 46 | qsort(word, nword, sizeof(word[0]), sortcmp); 47 | phrase = inputchars; 48 | for ( ; wordsleft > 0; wordsleft--) { 49 | l = -1; 50 | u = nword; 51 | while (l+1 != u) { 52 | m = (l + u) / 2; 53 | if (wordncmp(word[m], phrase) < 0) 54 | l = m; 55 | else 56 | u = m; 57 | } 58 | for (i = 0; wordncmp(phrase, word[u+i]) == 0; i++) 59 | if (rand() % (i+1) == 0) 60 | p = word[u+i]; 61 | phrase = skip(p, 1); 62 | if (strlen(skip(phrase, k-1)) == 0) 63 | break; 64 | printf("%s\n", skip(phrase, k-1)); 65 | } 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /part-3/column-15/markovhash.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* markovhash.c -- generate random text, sped up with hash tables */ 5 | 6 | /* For storage efficiency (and also to minimize changes from markov.c), 7 | the hash table is implemented in the integer array next. 8 | If bin[i]=j, then word[j] is the first element in the list, 9 | word[next[j]] is the next element, and so on. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | char inputchars[4300000]; 17 | #define MAXWORDS 800000 18 | char *word[MAXWORDS]; 19 | int nword = 0; 20 | int k = 2; 21 | 22 | int next[MAXWORDS]; 23 | #define NHASH 499979 24 | int bin[NHASH]; 25 | #define MULT 31 26 | 27 | unsigned int hash(char *ptr) 28 | { unsigned int h = 0; 29 | unsigned char *p = ptr; 30 | int n; 31 | for (n = k; n > 0; p++) { 32 | h = MULT * h + *p; 33 | if (*p == 0) 34 | n--; 35 | } 36 | return h % NHASH; 37 | } 38 | 39 | int wordncmp(char *p, char* q) 40 | { int n = k; 41 | for ( ; *p == *q; p++, q++) 42 | if (*p == 0 && --n == 0) 43 | return 0; 44 | return *p - *q; 45 | } 46 | 47 | int sortcmp(char **p, char **q) 48 | { return wordncmp(*p, *q); 49 | } 50 | 51 | char *skip(char *p, int n) 52 | { for ( ; n > 0; p++) 53 | if (*p == 0) 54 | n--; 55 | return p; 56 | } 57 | 58 | int main() 59 | { int i, wordsleft = 10000, j; 60 | char *phrase, *p; 61 | word[0] = inputchars; 62 | while (scanf("%s", word[nword]) != EOF) { 63 | word[nword+1] = word[nword] + strlen(word[nword]) + 1; 64 | nword++; 65 | } 66 | for (i = 0; i < k; i++) 67 | word[nword][i] = 0; 68 | for (i = 0; i < NHASH; i++) 69 | bin[i] = -1; 70 | for (i = 0; i <= nword - k; i++) { /* check */ 71 | j = hash(word[i]); 72 | next[i] = bin[j]; 73 | bin[j] = i; 74 | } 75 | for (i = 0; i < k; i++) 76 | printf("%s\n", word[i]); 77 | phrase = inputchars; 78 | for ( ; wordsleft > 0; wordsleft--) { 79 | i = 0; 80 | for (j = bin[hash(phrase)]; j >= 0; j = next[j]) 81 | if ((wordncmp(phrase, word[j]) == 0) 82 | && (rand() % (++i) == 0)) 83 | p = word[j]; 84 | phrase = skip(p, 1); 85 | if (strlen(skip(phrase, k-1)) == 0) 86 | break; 87 | printf("%s\n", skip(phrase, k-1)); 88 | } 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /part-3/column-15/markovlet.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2000 Lucent Technologies */ 2 | /* Modified from markov.c in 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* markovlet.c -- generate letter-level random text from input text 5 | Alg: Store text in an array on input 6 | Scan complete text for each output character 7 | (Randomly select one matching k-gram) 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | char x[5000000]; 14 | 15 | int main() 16 | { int c, i, eqsofar, max, n = 0, k = 5; 17 | char *p, *nextp, *q; 18 | while ((c = getchar()) != EOF) 19 | x[n++] = c; 20 | x[n] = 0; 21 | p = x; 22 | srand(1); 23 | for (max = 2000; max > 0; max--) { 24 | eqsofar = 0; 25 | for (q = x; q < x + n - k + 1; q++) { 26 | for (i = 0; i < k && *(p+i) == *(q+i); i++) 27 | ; 28 | if (i == k) 29 | if (rand() % ++eqsofar == 0) 30 | nextp = q; 31 | } 32 | c = *(nextp+k); 33 | if (c == 0) 34 | break; 35 | putchar(c); 36 | p = nextp+1; 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /part-3/column-15/wordfreq.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* wordfreq.c -- list of words in file, with counts */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct node *nodeptr; 11 | typedef struct node { 12 | char *word; 13 | int count; 14 | nodeptr next; 15 | } node; 16 | 17 | #define NHASH 29989 18 | #define MULT 31 19 | nodeptr bin[NHASH]; 20 | 21 | unsigned int hash(char *p) 22 | { unsigned int h = 0; 23 | for ( ; *p; p++) 24 | h = MULT * h + *p; 25 | return h % NHASH; 26 | } 27 | 28 | #define NODEGROUP 1000 29 | int nodesleft = 0; 30 | nodeptr freenode; 31 | 32 | nodeptr nmalloc() 33 | { if (nodesleft == 0) { 34 | freenode = malloc(NODEGROUP*sizeof(node)); 35 | nodesleft = NODEGROUP; 36 | } 37 | nodesleft--; 38 | return freenode++; 39 | } 40 | 41 | #define CHARGROUP 10000 42 | int charsleft = 0; 43 | char *freechar; 44 | 45 | char *smalloc(int n) 46 | { if (charsleft < n) { 47 | freechar = malloc(n+CHARGROUP); 48 | charsleft = n+CHARGROUP; 49 | } 50 | charsleft -= n; 51 | freechar += n; 52 | return freechar - n; 53 | } 54 | 55 | void incword(char *s) 56 | { nodeptr p; 57 | int h = hash(s); 58 | for (p = bin[h]; p != NULL; p = p->next) 59 | if (strcmp(s, p->word) == 0) { 60 | (p->count)++; 61 | return; 62 | } 63 | p = nmalloc(); 64 | p->count = 1; 65 | p->word = smalloc(strlen(s)+1); 66 | strcpy(p->word, s); 67 | p->next = bin[h]; 68 | bin[h] = p; 69 | } 70 | 71 | int main() 72 | { int i; 73 | nodeptr p; 74 | char buf[100]; 75 | for (i = 0; i < NHASH; i++) 76 | bin[i] = NULL; 77 | while (scanf("%s", buf) != EOF) 78 | incword(buf); 79 | for (i = 0; i < NHASH; i++) 80 | for (p = bin[i]; p != NULL; p = p->next) 81 | printf("%s %d\n", p->word, p->count); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /part-3/column-15/wordfreq.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* wordfreq.cpp -- List all words in input file, with counts */ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main() 12 | { map M; 13 | map::iterator j; 14 | string t; 15 | while (cin >> t) 16 | M[t]++; 17 | for (j = M.begin(); j != M.end(); ++j) 18 | cout << j->first << " " << j->second << "\n"; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /part-3/column-15/wordlist.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1999 Lucent Technologies */ 2 | /* From 'Programming Pearls' by Jon Bentley */ 3 | 4 | /* wordlist.cpp -- Sorted list of words (between white space) in file */ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main() 12 | { set S; 13 | string t; 14 | set::iterator j; 15 | while (cin >> t) 16 | S.insert(t); 17 | for (j = S.begin(); j != S.end(); ++j) 18 | cout << *j << "\n"; 19 | return 0; 20 | } 21 | --------------------------------------------------------------------------------