Skip to content

Instantly share code, notes, and snippets.

@sethladd
Created December 9, 2013 05:46
Show Gist options
  • Save sethladd/7867811 to your computer and use it in GitHub Desktop.
Save sethladd/7867811 to your computer and use it in GitHub Desktop.
My humble entry for Dart Dare - Secret Santa. I'm sure there are smaller or faster ways to do this. However, I wanted to try to solve the problem with sorting and processing lists. The entire solution hinges on sorting the santas by last name and by family size. Features of Dart that I used: * Classes * String interpolation * Type annotations * …
class Person {
String firstName, lastName;
Person(List<String> raw) : firstName = raw[0], lastName = raw[1];
String toString() => '$firstName $lastName';
}
/**
* Expects one person per line, each line containing a first and last name
* separated by a single space.
*/
List<Person> parsePeople(String santas) {
return santas
.split('\n')
.map((e) => e.trim().split(' '))
.map((e) => new Person(e))
.toList();
}
/**
* Try the old "generate a big sorted list" approach. Sort all people
* by last name, and then sort again by biggest family down to smallest
* family. The actual pairing assumes this structure.
*/
List<Person> prepForGiftification(String santas) {
return ((parsePeople(santas)
// Group by last name.
..sort((p1, p2) => p1.lastName.compareTo(p2.lastName)))
// Create a list of lists, grouped by last name. Assumes the list is sorted.
.fold([[]], (List<List> list, person) {
var current = list.last;
if (current.isEmpty || current.last.lastName == person.lastName) {
current.add(person);
} else {
list.add([person]);
}
return list;
}) as List
// Order by biggest family first.
..sort((l1, l2) => l2.length.compareTo(l1.length)))
// Flatten the list of lists.
.expand((i) => i).toList();
}
/**
* Assumes a sorted list of people, sorted by biggest family to smallest
* family.
*
* TODO: any error handling at all.
*/
Map<Person, Person> pairUp(List<Person> santas) {
var pairs = {};
var currentPairing = santas.indexOf(santas.firstWhere((p) => p.lastName != santas[0].lastName));
for (var santa in santas) {
pairs[santa] = santas[currentPairing++];
if (currentPairing == santas.length) currentPairing = 0;
}
return pairs;
}
main() {
var input = '''
Zoe Washburne
Hoban Washburne
Malcolm Reynolds
Simon Tam
River Tam
Buffy Summers
Dawn Summers''';
var people = prepForGiftification(input);
var pairs = pairUp(people);
print(pairs);
}
@sethladd
Copy link
Author

sethladd commented Dec 9, 2013

See original Dart Dare description and other solutions: https://plus.google.com/+SethLadd/posts/XjgFRvqtVA4

@MarkBennett
Copy link

@sethladd why did you use the : syntax in the Person constructor on line 3, rather than parsing the raw string into first name last name in the constructor body?

@spiechu
Copy link

spiechu commented Dec 9, 2013

@MarkBennett i think it is preparation for optional firstname/lastname lockdown by final keyword. All final fields must be initialized before constructor body begins to run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment