RosettaCodeData/Task/Random-sentence-from-book/Dart/random-sentence-from-book.dart
2026-04-30 12:34:36 -04:00

44 lines
1.5 KiB
Dart

import 'dart:io';
import 'package:collection/collection.dart';
import 'package:more/more.dart';
var heading = RegExp(r'^[ ABCDEFGHIJKLMNOPQRSTUVWXYZ\-\.?“”]+$');
Function eq = const ListEquality().equals;
main() {
var text = File('bin/_other/war_of_the_worlds.txt')
.readAsLinesSync()
.skipTo('BOOK ONE')
.where((e) => e.isNotEmpty)
.where((e) => !heading.hasMatch(e))
.takeWhile((e) => !e.startsWith('*** END OF THE PROJECT'))
.join(' ')
.replaceAll(RegExp(r'; |, |: '), ' ')
.replaceAll(RegExp(r'“|”|(|)'), '')
.replaceAll('. ', ' . ');
var tokens = '. $text'.split(' ');
var pairs = Multiset.from(tokens.window(2));
var triples = Multiset.from(tokens.window(3));
var gen = ['.'];
var cands = pairs.entrySet.where((e) => e.key.first == gen.last).toList();
gen.add(cands[getWeightedNext(cands)].key.last);
for (var _ in 0.to(200)) {
var cands = triples.entrySet
.where((e) => eq(e.key.take(2).toList(), gen.takeLast(2).toList()))
.toList();
gen.add(cands[getWeightedNext(cands)].key.last);
}
var sentences = gen
.splitAfter((e) => e == '.')
.skip(1)
.map((e) => '${(e..removeLast()).join(' ')}.')
.toList()
..removeLast();
sentences.forEach((e) => print(e));
}
int getWeightedNext(List<MapEntry<List<String>, int>> cands) {
var offsets = cands.fold([0], (s, t) => s..add(s.last + t.value));
var pick = 0.to(offsets.last).atRandom();
return offsets.skipWhile((e) => e < pick).first;
}