-
Notifications
You must be signed in to change notification settings - Fork 1
/
demoPM.py
executable file
·149 lines (124 loc) · 4.58 KB
/
demoPM.py
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python
import sys
# ------------------------------------------------------------------#
# function to check if a string contains vowels
# ------------------------------------------------------------------#
def hasVowel(inString):
vowels = ['a','e','i','o','u']
letters = list(inString)
return any(letter in letters for letter in vowels)
# ------------------------------------------------------------------#
# function to split word into trios e.g. reddit -> red, edd, ddi, dit
# ------------------------------------------------------------------#
def letterTrios(inString):
trios = []
letters = list(inString)
for letterPos, letter in enumerate(letters):
if letterPos == len(letters)-2:
break
nextLetter = letters[letterPos+1]
nextNextLetter = letters[letterPos+2]
trio = letter+nextLetter+nextNextLetter
trios.append(trio)
return trios
# ------------------------------------------------------------------#
# function to make a portmanteau of stringA and stringB by triple letters
# ------------------------------------------------------------------#
def makepmByTrios(stringA, stringB):
# find all shared trios and their positions in each string
aTrios = letterTrios(stringA)
bTrios = letterTrios(stringB)
if len(aTrios) < 3 or len(bTrios) < 3:
return "FAIL: word too short for trios"
aTrios = aTrios[1:]
bTrios = bTrios[:-2]
# look for shared trios
hasSharedTrios = False
posOfTrios = []
for aPos, aTrio in enumerate(aTrios):
if hasSharedTrios:
break
for bPos, bTrio in enumerate(bTrios):
if hasSharedTrios:
break
if aTrio == bTrio:
hasSharedTrios = True
#print "Found shared trio, '"+aTrio+"' at ("+str(aPos)+","+str(bPos)+")"
posOfTrios.append(aPos+1)
posOfTrios.append(bPos)
# check if both strings have shared trios
if not hasSharedTrios:
return "FAIL: don't have shared trios"
# put together and return portmanteau
outA = stringA[:posOfTrios[0]] # everything up to and EXcluding the chosen trio in string A
outB = stringB[posOfTrios[1]:] # everything after and INcluding the chosen trio in string B
return outA+outB
# ------------------------------------------------------------------#
# function to make a portmanteau of stringA and stringB.
# ------------------------------------------------------------------#
def makepm(stringA, stringB):
# try to make pm by pairs first
triopm = makepmByTrios(stringA, stringB)
if "FAIL" not in triopm:
return triopm
# check if both strings have at least 1 vowel
if not hasVowel(stringA) or not hasVowel(stringB):
return "FAIL: don't have vowels in both strings"
# find all vowels and their positions in each string
vowels = ['a','e','i','o','u']
aVowels = []
bVowels = []
for aLetter in stringA:
if aLetter in vowels:
aVowels.append(aLetter)
else:
aVowels.append("")
for bLetter in stringB:
if bLetter in vowels:
bVowels.append(bLetter)
else:
bVowels.append("")
# see if A and B have any vowels in common
haveCommonVowels = False
shouldUseCommonVowels = False
vowelPairPositions = []
for aVowelPos, aVowel in enumerate(aVowels):
for bVowelPos, bVowel in enumerate(bVowels):
if aVowel == bVowel and aVowel != "":
vowelPairPositions.append([aVowelPos,bVowelPos])
haveCommonVowels = True
# place to record positions of vowels we decide to use
posOfVowelsToUse = [-1,-1]
# if we have common vowels, choose whether to use them based on position
if haveCommonVowels:
margin = 2 # guarantees output satisfies len(pm) > 2*margin
for vowelPairPosition in vowelPairPositions:
if vowelPairPosition[0] < margin or vowelPairPosition[1] >= len(stringB)-margin:
continue
else:
posOfVowelsToUse = vowelPairPosition
shouldUseCommonVowels = True
break
# if not using common vowels, just pick any vowels based on position
if not shouldUseCommonVowels:
aVowelPos = -1
bVowelPos = len(stringB)+1
for aVowelIndex, aVowel in enumerate(aVowels):
if aVowel != "" and aVowelIndex > aVowelPos:
aVowelPos = aVowelIndex
for bVowelIndex, bVowel in enumerate(bVowels):
if bVowel != "" and bVowelIndex < bVowelPos:
bVowelPos = bVowelIndex
posOfVowelsToUse[0] = aVowelPos
posOfVowelsToUse[1] = bVowelPos
# put together and return portmanteau
outA = stringA[:posOfVowelsToUse[0]] # everything up to and EXcluding the chosen vowel in string A
outB = stringB[posOfVowelsToUse[1]:] # everything after and INcluding the chosen vowel in string B
return outA+outB
# check inputs
inputs = sys.argv
if len(inputs) != 3:
print "Need to provide 2 arguments"
exit()
outputPM = makepm(inputs[1],inputs[2])
print "Output portmanteau is '"+outputPM+"'"