## Intersecting Number Wheels

### October 1, 2019

Our implementation follows the description exactly:

```(define-generator (wheel xs)
(let loop ((ws (cycle xs)))
(if (integer? (car ws))
(yield (car ws))
(yield ((eval (car ws)))))
(loop (cdr ws))))```

Here are the examples from the Rosetta Code description:

```> (define a (wheel '(1 2 3)))
> (take-gen 20 a)
(1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2)
> (define a (wheel '(1 b 2)))
> (define b (wheel '(3 4)))
> (take-gen 20 a)
(1 3 2 1 4 2 1 3 2 1 4 2 1 3 2 1 4 2 1 3)
> (define a (wheel '(1 d d)))
> (define d (wheel '(6 7 8)))
> (take-gen 20 a)
(1 6 7 1 8 6 1 7 8 1 6 7 1 8 6 1 7 8 1 6)
> (define a (wheel '(1 b c)))
> (define b (wheel '(3 4)))
> (define c (wheel '(5 b)))
> (take-gen 20 a)
(1 3 5 1 4 3 1 4 5 1 3 4 1 3 5 1 4 3 1 4)```

You can see the assembled program at https://ideone.com/lpMU0a, but it doesn’t run, I don’t know why, something to do with the `define-generator` macro. I can assure you it runs fine in Chez Scheme on my systems at home and work.

Pages: 1 2

### 5 Responses to “Intersecting Number Wheels”

1. chaw said

Here is a very simple solution using only R7RS Scheme plus
circular-list from SRFI 1 (and unfold for a demo). It is avoids eval
but uses destructive updates. It also requires the wheels to be
defined without forward references, which could be considered a
feature that disallows wheels like A = (B) with B = (A).

``` (import (scheme base) (scheme write) (only (srfi 1) circular-list unfold)) (define (number-wheel . vals) (let ((clst (apply circular-list vals))) (lambda () (let ((v (car clst))) (set! clst (cdr clst)) (if (procedure? v) (v) v))))) (define (demo) (define B (number-wheel 3 4)) (define A (number-wheel 1 B 2)) (display (unfold (lambda (s) (>= s 20)) (lambda (s) (A)) (lambda (s) (+ s 1)) 0)) (newline)) (demo) ```

Output:

``` (1 3 2 1 4 2 1 3 2 1 4 2 1 3 2 1 4 2 1 3) ```

2. matthew said

Here’s a C++ solution, read the wheels from the command line, 1st arg is for A, 2nd for B etc. Store in array and use second array to store current offset for each wheel:

```#include <iostream>
#include <vector>
#include <string>

int main(int argc, char *argv[]) {
std::vector<std::string> wheels(argv+1,argv+argc);
std::vector<int> state(wheels.size());
for (int i = 0; i < 20; i++) {
int n = 0;
while(true) {
char c = wheels[n][state[n]];
state[n] = (state[n]+1)%wheels[n].size();
if (isdigit(c)) {
std::cout << c;
break;
}
n = c-'A';
}
}
std::cout << "\n";
}
```
```\$ g++ -Wall wheel.cpp -o wheel
\$ ./wheel 1BC 34 5B
13514314513413514314
```
3. matthew said
```\$ ./wheel 1B2 34
13214213214213214213
```
4. matthew said

A better version:

```#include <iostream>
#include <vector>
#include <string>

class Wheels {
public:
template <typename IT>
Wheels(IT start, IT end)
: wheels(start,end), state(wheels.size()) {
}
int operator()() {
int n = 0;
while (true) {
char c = wheels[n][state[n]];
state[n] = (state[n]+1)%wheels[n].size();
if (isdigit(c)) return c-'0';
else n = c-'A';
}
}
private:
std::vector<std::string> wheels;
std::vector<int> state;
};

int main(int argc, char *argv[]) {
Wheels wheels(argv+1,argv+argc);
for (int i = 0; i < 20; i++) {
std::cout << wheels();
}
std::cout << "\n";
}
```
5. Daniel said

Here’s a solution in Python.

```from collections import deque, OrderedDict

def gen(wheels):
wheel = first = wheels[next(iter(wheels))]
while True:
value = wheel[0]
wheel.rotate(-1)
if isinstance(value, int):
wheel = first
yield value
else:
wheel = wheels[value]

wheels = OrderedDict((
('A', deque([1, 'B', 2])),
('B', deque([3, 4])),
))

for x in gen(wheels):
print(x)
```

Output:

```1
3
2
1
4
2
1
3
2
1
4
2
...
```