import random def generate_song_title(): adjectives = [ # Colors & Light "gentle", "quiet", "distant", "silver", "golden", "crystal", "velvet", "misty", "serene", "tender", "whispered", "floating", "dreamy", "soft", "mellow", "tranquil", "peaceful", "calm", "ethereal", "delicate", "subtle", "graceful", "luminous", "pale", "amber", "ivory", "pearl", "opal", "sapphire", "emerald", "crimson", "violet", "indigo", "turquoise", "copper", "bronze", # Textures & Feelings "smooth", "silken", "feathered", "quilted", "woven", "polished", "hushed", "muted", "gentle", "soothing", "warming", "cooling", "flowing", "rippling", "swaying", "drifting", "gliding", "soaring", "nestled", "cradled", "embraced", "sheltered", "protected", "safe", # Time & Space "eternal", "infinite", "boundless", "fleeting", "passing", "lingering", "distant", "nearby", "faraway", "close", "approaching", "departing", "ascending", "descending", "circling", "spiraling", "meandering", "wandering", # Nature-inspired "dewy", "misty", "foggy", "cloudy", "sunny", "moonlit", "starlit", "shadowed", "dappled", "filtered", "reflected", "mirrored", "blooming", "budding", "unfurling", "opening", "closing", "resting" ] nouns = [ # Time periods "morning", "evening", "shadow", "light", "rain", "cloud", "river", "ocean", "mountain", "valley", "garden", "meadow", "breeze", "dawn", "dusk", "star", "moon", "sky", "reflection", "echo", "memory", "dream", "moment", "silence", "afternoon", "midnight", "twilight", "daybreak", "nightfall", "sunrise", "sunset", "moonrise", "starlight", "candlelight", "firelight", "lamplight", # Natural elements "mist", "fog", "dew", "frost", "snow", "ice", "stone", "pebble", "sand", "dust", "ash", "ember", "leaf", "petal", "bloom", "blossom", "branch", "root", "wave", "tide", "current", "stream", "brook", "pond", "hill", "cliff", "shore", "beach", "cove", "bay", # Abstract concepts "thought", "feeling", "notion", "idea", "sense", "touch", "whisper", "murmur", "sigh", "breath", "pause", "rest", "journey", "passage", "crossing", "bridge", "threshold", "doorway", "window", "mirror", "veil", "curtain", "screen", "shade", # Places & Spaces "chamber", "room", "hall", "corridor", "path", "trail", "forest", "grove", "glade", "clearing", "hollow", "dell", "field", "plain", "prairie", "steppe", "tundra", "desert", "island", "peninsula", "archipelago", "lagoon", "reef", "atoll" ] modifiers = [ "endless", "forgotten", "hidden", "ancient", "timeless", "sacred", "wandering", "dancing", "sleeping", "waking", "drifting", "fading", "rising", "falling", "turning", "spinning", "floating", "sinking", "growing", "shrinking", "expanding", "contracting", "pulsing", "breathing", "whispering", "singing", "humming", "sighing", "calling", "beckoning", "glowing", "dimming", "flickering", "shimmering", "sparkling", "gleaming" ] connectors = [ "of", "in", "on", "by", "for", "with", "under", "over", "through", "between", "among", "within", "without", "beneath", "above", "across", "along", "around", "behind", "before" ] articles_no_an = ["the", "this", "that", "my", "your", "our"] def get_article(word): """Return 'a' or 'an' based on the starting sound of the word""" vowel_sounds = ['a', 'e', 'i', 'o', 'u'] word_lower = word.lower() # Handle special cases where spelling doesn't match sound # Silent H words (use 'an') if word_lower in ['hour', 'honest', 'honor', 'heir', 'hourly', 'honesty']: return 'an' # Words starting with 'u' that sound like 'yu' (use 'a') elif word_lower in ['one', 'once', 'uniform', 'university', 'unique', 'union', 'unit', 'united', 'universal', 'unicorn']: return 'a' # Words starting with vowels but consonant sounds elif word_lower.startswith('eu') and word_lower in ['european', 'eucalyptus', 'euphemism']: return 'a' # Check if it starts with a vowel sound elif word[0].lower() in vowel_sounds: return 'an' else: return 'a' def choose_article_for(word): """Choose an article, handling a/an correctly""" if random.random() < 0.3: # 30% chance of a/an return get_article(word) else: return random.choice(articles_no_an) # Note: Using walrus operator (:=) to capture the word before applying article selection # This ensures the article matches the word that follows it patterns = [ # Simple patterns lambda: f"{random.choice(adjectives)} {random.choice(nouns)}", lambda: (adj := random.choice(adjectives), f"{choose_article_for(adj)} {adj} {random.choice(nouns)}")[1], lambda: f"{random.choice(modifiers)} {random.choice(nouns)}", # Compound patterns lambda: f"{random.choice(nouns)} {random.choice(connectors)} {random.choice(nouns)}", lambda: (noun := random.choice(nouns), adj := random.choice(adjectives), f"{choose_article_for(noun)} {noun} {random.choice(connectors)} {adj} {random.choice(nouns)}")[2], lambda: f"{random.choice(adjectives)} {random.choice(nouns)} {random.choice(connectors)} {random.choice(nouns)}", # Possessive patterns lambda: (adj := random.choice(adjectives), f"{choose_article_for(adj)} {adj} {random.choice(nouns)}'s {random.choice(nouns)}")[1], lambda: f"{random.choice(nouns)}'s {random.choice(adjectives)} {random.choice(nouns)}", # Complex patterns lambda: (adj := random.choice(adjectives), f"{random.choice(connectors)} {choose_article_for(adj)} {adj} {random.choice(nouns)}")[1], lambda: f"{random.choice(modifiers)} {random.choice(nouns)} {random.choice(connectors)} {random.choice(adjectives)} {random.choice(nouns)}", lambda: (noun := random.choice(nouns), modifier := random.choice(modifiers), f"{choose_article_for(noun)} {noun} {random.choice(connectors)} {modifier} {random.choice(nouns)}")[2], # Poetic patterns lambda: f"when {random.choice(nouns)} {random.choice(modifiers)}", lambda: f"where {random.choice(adjectives)} {random.choice(nouns)} {random.choice(modifiers)}", lambda: (noun := random.choice(nouns), f"as {choose_article_for(noun)} {noun} {random.choice(modifiers)}")[1], # Number patterns (for even more variety) lambda: f"{random.choice(['one', 'two', 'three', 'seven', 'twelve', 'hundred', 'thousand'])} {random.choice(adjectives)} {random.choice(nouns)}", lambda: f"{random.choice(nouns)} {random.choice(['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'])}", # Time-based patterns lambda: f"{random.choice(['first', 'last', 'next', 'final', 'eternal'])} {random.choice(nouns)}", lambda: (adj := random.choice(adjectives), f"{random.choice(['before', 'after', 'during', 'beyond'])} {choose_article_for(adj)} {adj} {random.choice(nouns)}")[1], # Double adjective patterns lambda: f"{random.choice(adjectives)}, {random.choice(adjectives)} {random.choice(nouns)}", lambda: (adj1 := random.choice(adjectives), adj2 := random.choice(adjectives), f"{choose_article_for(adj1)} {adj1} and {adj2} {random.choice(nouns)}")[2] ] def proper_title_case(text): """Apply proper title case rules""" # Words that should remain lowercase (unless first or last) lowercase_words = { 'a', 'an', 'and', 'as', 'at', 'but', 'by', 'for', 'from', 'in', 'into', 'nor', 'of', 'on', 'or', 'out', 'over', 'so', 'the', 'to', 'up', 'with', 'yet', 'under', 'above', 'across', 'after', 'along', 'among', 'around', 'before', 'behind', 'beneath', 'between', 'beyond', 'during', 'through', 'throughout', 'within', 'without' } words = text.split() result = [] for i, word in enumerate(words): # Handle possessives if "'" in word: parts = word.split("'") parts[0] = parts[0].capitalize() word = "'".join(parts) result.append(word) # First or last word is always capitalized elif i == 0 or i == len(words) - 1: result.append(word.capitalize()) # Check if it should be lowercase elif word.lower() in lowercase_words: result.append(word.lower()) # Otherwise capitalize else: result.append(word.capitalize()) return ' '.join(result) # Generate the title title = random.choice(patterns)() return proper_title_case(title) # Example usage if __name__ == "__main__": print("=== 50 Anodyne Song Titles ===\n") for i in range(50): print(f"{i+1:2d}. {generate_song_title()}")