Last active
August 29, 2015 13:57
-
-
Save dela3499/9382995 to your computer and use it in GitHub Desktop.
Auto-generating interesting names (a la Figure)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(require '[clojure.string :as string]) | |
(defn insert-at [n coll elem] | |
"Insert elem as nth element of coll" | |
(let [[a b] (split-at n coll)] | |
(concat a [elem] b))) | |
(defn sample [coll n] | |
"Get n random samples from coll" | |
(repeatedly n #(rand-nth coll))) | |
(defn capitalize-words [s] | |
"Capitalize every word in a string" | |
(->> (string/split s #"\b") | |
(map string/capitalize) | |
(string/join))) | |
(defn get-random-name | |
"Get a random name with following constraints: | |
- has 6, 8, or 10 characters total | |
- name starts with consonant | |
- characters alternate between consonants and vowels | |
- name is either one or two capitalized words | |
- if two words, the first word is 2 or four characters long" | |
([] "Return a single name" | |
(let [n (rand-nth [3 4 5]) | |
consonants "bcdfghjklmnpqrstv" | |
vowels "aeiouy"] | |
(->> (interleave (sample consonants n) | |
(sample vowels n)) | |
((rand-nth [identity | |
#(insert-at (rand-nth [2 4]) % " ")])) | |
(apply str) | |
(capitalize-words)))) | |
([n] "Return n names" | |
(repeatedly n get-random-name))) | |
(doseq [name (get-random-name 10)] | |
(println name)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Graphics.Element exposing (show) | |
import Random exposing (..) | |
import Time exposing (second,every) | |
import Signal exposing (map,(<~)) | |
import String exposing (toList) | |
import Array exposing (length,get,fromList,Array) | |
import List exposing (map,take,drop) | |
import Char | |
main = show <~ Signal.map (\x -> generateConfig (initialSeed (floor x)) |> getName) (every second) | |
type Length = | |
Everything | Len Int | |
type alias Config = | |
{vIndices: List Int, | |
cIndices: List Int, | |
length: Length} | |
generateConfig: Seed -> Config | |
generateConfig seed1 = | |
let (nChars, seed2) = generate (int 3 5) seed1 | |
(vIndices, seed3) = generate (list nChars (int 0 1000)) seed2 | |
(cIndices, seed4) = generate (list nChars (int 0 1000)) seed3 | |
(length, seed5) = generate (int 0 2) seed4 | |
config = {vIndices = vIndices, | |
cIndices = cIndices} | |
in | |
if length == 0 | |
then {config | length = Everything} | |
else {config | length = Len (2 * length)} | |
getName: Config -> String | |
getName config = | |
let getLetters xs is = List.map (\i -> modGetChar i xs) is | |
vowels = getLetters "aeiouy" config.vIndices | |
consonants = getLetters "bcdfghjklmnpqrstv" config.cIndices | |
letters = interleave consonants vowels | |
in | |
case config.length of | |
Len x -> | |
letters | |
|> splitAt x | |
|> List.map String.fromList | |
|> List.map capitalize | |
|> String.join " " | |
Everything -> | |
letters | |
|> String.fromList | |
|> capitalize | |
modGet: Int -> Array a -> Maybe a | |
modGet i xs = | |
let j = i % (Array.length xs) | |
in Array.get j xs | |
modGetChar: Int -> String -> Char | |
modGetChar i s = | |
let x = modGet i (s |> String.toList |> Array.fromList) | |
in case x of | |
Just chara -> chara | |
Nothing -> 'a' | |
capitalize: String -> String | |
capitalize s = | |
let parts = String.uncons s | |
in case parts of | |
Just (h,t) -> String.cons (Char.toUpper h) t | |
Nothing -> "" | |
zip: List a -> List b -> List (a,b) | |
zip a b = | |
List.map2 (,) a b | |
interleave: List a -> List a -> List a | |
interleave a b = | |
zip a b | |
|> List.map (\(a,b) -> [a,b]) | |
|> List.concat | |
splitAt: Int -> List a -> List (List a) | |
splitAt i xs = | |
[take i xs, drop i xs] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; | |
;;; The Figure music-creation mobile app (http://www.propellerheads.se/products/figure/) | |
;;; has a file auto-naming feature I thought I'd reproduce in different languages. | |
;;; | |
;;; After completing the Lisp Koans (https://github.com/google/lisp-koans), I thought I'd | |
;;; give Common Lisp a try. I compared the length of Common Lisp, Python, and Ruby versions and found | |
;;; Lisp to produce the most concise code (if general utility functions aren't included in program length). | |
;;; | |
;;; From what I could tell, all the random names generated by Figure followed this specification: | |
;;; - 6, 8, or 10 letters. | |
;;; - alternating consonants and vowels (any vowel allowed, and all consonants but w,x,y or z) | |
;;; - one or two words (each with first character capitalized) | |
;;; - (optionally, if making two words) a space after the first or second pair of letters | |
;;; Note: The last function shown reproduces a bug that hasn't yet been fixed. | |
;;; the macro "defun-with-optional-repeat" can only currently be used to define functions that take zero arguments | |
(setf *random-state* (make-random-state t)) ;req'd for random number creation | |
(defun stringify (x) | |
(coerce x 'string)) | |
(defun listify (x) | |
(coerce x 'list)) | |
(defun get-random-element (x) | |
"Returns a random element of a sequence." | |
(if (and x (typep x 'sequence)) | |
(elt x (random (length x))) | |
(error "Argument to get-random-element empty or not a sequence"))) | |
(defmacro defun-with-recursion (fname args &key start exec-when-atom) | |
(let ((arg (car args))) `(defun ,fname ,args | |
(progn ,start) | |
(cond ((null ,arg) nil) | |
((atom ,arg) (,exec-when-atom ,arg)) | |
(t (mapcan #' ,fname ,arg)))))) | |
(defun-with-recursion nice-print (x) | |
:start (fresh-line) | |
:exec-when-atom princ) | |
(defun-with-recursion flatten (x) | |
:exec-when-atom list) | |
(defun insert-nth (x n list) | |
"insert x into nth place in list" | |
(if (and n (> n 0)) | |
(append (subseq list 0 n) (list x) (subseq list n)) | |
list));no insertion in this case (n < 0 or is nil) | |
(defun exec-n-times (n f &rest other) | |
"evaluate function (f) for (n) times and store output in list" | |
(mapcar #'(lambda (x) (apply f other)) (make-list n))) | |
(defmacro defun-with-optional-repeat (fname fargs body) | |
`(defun ,fname ,(append fargs '(&optional n)) | |
(if n | |
(exec-n-times n #' ,fname) ;; this will fail for functions with required arguments (since no arguments are passed to exec-n-times) | |
,body))) | |
(defun-with-optional-repeat create-name () | |
(string-capitalize (stringify | |
(insert-nth #\space (get-random-element '(nil 2 4)) (flatten | |
(mapcar (lambda (x) | |
(mapcar #'get-random-element '("bcdfghjklmnpqrstv" "aeiouy"))) | |
(make-list (get-random-element '(3 4 5))))))))) | |
(nice-print (create-name 10)) | |
(defun-with-optional-repeat show-macro-failure (a) | |
a) ; this macro fails as specified in its definition above | |
; (nice-print (show-macro-failure 1 2)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""This is a python version of the same random name generator""" | |
from string import ascii_lowercase as az | |
from random import choice | |
from itertools import * | |
def flatten(listOfLists): | |
"Flatten one level of nesting" | |
return list(chain.from_iterable(listOfLists)) | |
def get_letters(n): | |
vowels = list('aeiouy') | |
consonants = list(set(list(az)) - set(list('wxyz')) - set(vowels)) | |
return_vowels = [choice(vowels) for i in range(n/2)] | |
return_consonants = [choice(consonants) for i in range(n/2)] | |
return flatten(zip(return_consonants,return_vowels)) | |
def get_name(): | |
my_word = ''.join(get_letters(choice([6,8,10]))) | |
l = choice([2,4]) | |
my_words = ''.join([my_word[0:l],' ', my_word[l:]]) | |
my_name = choice([my_word,my_words]) | |
return my_name.title() | |
names = [get_name() for i in range(10)] | |
for name in names : print name |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Another random name generator - but this time in Ruby | |
def get_letters(n = 6) | |
vowels = 'aeiouy'.split('') | |
consonants = ('a'..'z').to_a - 'wxyz'.split('') - vowels | |
return_vowels = Array.new(n/2).map{vowels.sample} | |
return_consonants = Array.new(n/2).map{consonants.sample} | |
return return_consonants.zip(return_vowels).flatten | |
end | |
def get_name | |
letters = get_letters([6,8,10].sample).join | |
name = [letters, letters.insert([2,4].sample,' ')].sample | |
return name.split.map{|name| name.capitalize}.join(' ') | |
end | |
n = 10 ; puts Array.new(n).map{get_name} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment