summaryrefslogtreecommitdiff
path: root/Homework/cs4700/dart/streams.dart
blob: b7d7b26eeee670fb723ba04580b751c7abb69a8b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import 'dart:io';

// Generates a stream of n fibonacci numbers, sleeping 1 second every iteration
Stream<int> Function() fibonnaciNumbers(int n) {
  final Stream<int> Function() func = (() async* {
    var x = 0, y = 1;
    for (int i = 0; i <= n; i++) {
      yield x;
      sleep(new Duration(seconds: 1));
      y += x;
      x = y - x;
    }
  });
  return func;
}

// Filters a stream of integers with a function predicate determining to each of the elements in the stream.
Stream<int> Function() streamFilter(Stream<int> stream, bool Function(int) f) {
  final Stream<int> Function() func = (() async* {
    await for (var i in stream) {
      if (f(i)) {
        yield i;
      }
    }
  });
  return func;
}

// Iterates over a stream, accumulatively applying a binary function to a stream of integers until the last
// element and returns the accumulation.
Stream<int> Function() streamAccumulation(
    Stream<int> stream, int Function(int, int) f, initial) {
  final Stream<int> Function() func = (() async* {
    int a = initial;
    await for (var i in stream) {
      a = f(a, i);
      yield a;
    }
  });
  return func;
}

Stream<int> Function() generateNumbers(int n) {
  final Stream<int> Function() func = (() async* {
    for (int i = 1; i <= n; i++) {
      await Future<void>.delayed(const Duration(seconds: 1));
      yield i;
    }
  });
  return func;
}

// Given a list of lists, returns a list containing all the non-null elements of each list into a single list
List? flatten(List<List?>? aList) {
  if (aList == null) return null;
  return aList
      .where((i) => i != null)
      .expand((i) => i!)
      .where((i) => i != null)
      .toList();
}

// Generates a nested list where each element's index i is in a sublist of depth i+1.
// For example, deepen([1,2,3]) => [1, [2, [3]]]
List? deepen(List? aList) {
  if (aList == null) return null;
  return aList.reversed
      .fold([], (a, x) => (a != null && a.isEmpty) ? [x] : [x, a]);
}

void main(List<String> arguments) async {
  print('flattening [[0,1], [2]] yields ${flatten([
        [0, 1],
        [2]
      ])}');
  print('flattening [[0,1], [2], null] yields ${flatten([
        [0, 1],
        [2],
        null
      ])}');
  print('flattening [[0,1, null], [2]] yields ${flatten([
        [0, 1, null],
        [2]
      ])}');
  print('flattening null yields ${flatten(null)}');
  print('flattening [null] yields ${flatten([null])}');
  print('deepening [0,1,2] yields ${deepen([0, 1, 2])}');
  print('deepening [0,null,2] yields ${deepen([0, null, 2])}');
  print('deepening [0] yields ${deepen([0])}');
  print('deepening [] yields ${deepen([])}');
  print('deepening null yields ${deepen(null)}');
  await for (final number in fibonnaciNumbers(7)()) {
    print('fibonnaci number is ${number}');
  }
  await for (final number in streamFilter(generateNumbers(10)(), ((a) {
    return a % 2 == 0;
  }))()) {
    print('filtered number is $number');
  }

  await for (final number in streamAccumulation(generateNumbers(10)(), ((a, b) {
    return a + b;
  }), 0)()) {
    print('cumulative number is $number.');
  }
}