I'm trying to write a pig latin translator in F#. To translate, I need to know if a word starts with a vowel or not. To do that, I'm trying to use this function which I wrote...
(*Tests if an element is in a list*)
let isInList elementToFind listToCheck =
List.fold(fun a b -> a || b = elementToFind) false listToCheck;
to test if the first character in a word is in a list of all vowels. Here is what my attempt looks like
(*Takes a word and translates it to pig latin*)
let translateWord wordToTranslate : string =
let startsWithVowel = isInList(wordToTranslate.[0], ['A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u']);
if startsWithVowel then
translateWordStartingWithVowel(wordToTranslate)
else
translateWordStartingWithConsenant(wordToTranslate);
Which is giving several errors. It's saying wordToTranslate.[0] doesn't have enough type constrants and startsWithVowel is of the wrong type. The full error texts are
Severity Code Description Project File Line
Error The operator 'expr.[idx]' has been used on an object of indeterminate type based on information prior to this program point. Consider adding further type constraints Pig Latin FSharp
Severity Code Description Project File Line
Error This expression was expected to have type
bool
but here has type
('a * (char * char * char * char * char * char * char * char * char * char) list) list -> bool Pig Latin FSharp
How can I fix this approach so that it does what I want it to do? I'm relatively new to F# so any help would be greatly appreciated!
You need parenthesis in the type annotation, otherwise it applies to the return value, not parameter:
let translateWord (wordToTranslate : string) = ...
You do not need parenthesis and commas when passing arguments to isInList function. To separate elements of a list use ; instead of , (, is used to separate elements of a tuple).
let startsWithVowel = isInList wordToTranslate.[0] ['A'; 'E'; 'I'; 'O'; 'U'; 'a'; 'e'; 'i'; 'o'; 'u']
That will fix the compilation errors.
By the way, the following is cleaner, faster and will give you the same results:
let startsWithVowel = Seq.contains wordToTranslate.[0] "AEIOUaeiou"
Related
Right now I have the following code...
%strings = ( 'a' => 'x',
'b0' => 'y',
'b1' => 'y',
'b2' => 'y',
...
'bN' => 'y'
'c' => 'z');
....
if(grep { $_ eq $line[0] } keys %strings){
....
}
So over all I setup this hash. $line is created by reading a file. I then look to see if the first string in the line is contained within my hash. This code works perfectly. However, my problem arises with the fact that in the hash, b is growing. For instance right now I have to explicitly list out b0 - b63. This is 64 different definitions that all just need to have the same value. Is there a way to have a regex for the hash key like b\/d\?
If you want to use a regular expression, nothing prevents you from doing so:
%strings = (
'a' => 'x',
'b\d+' => 'y',
'c' => 'z'
);
...
if( grep { $line[0] =~ /^$_$/ } keys %strings ) {
...
}
The ^ and $ are necessary to make sure the full string $line[0] matches and not only a part of it.
Bear in mind that this will be much slower than the eq comparison. On the other hand, the number of expressions to evaluate by grep will be much lower, so you may want to profile different options if the speed of execution is an issue.
Also, keep in mind that you may want to refine the regular expression. For instance, ^b\d{1,2}$ will match a b followed by one or two digits. Or even ^b[1-6]?\d$...
If I undestood you correctly,
b\d+
This will match "b" followed by any string of only numbers.
my %strings = ('a' => 'x',
map{("b$_" , 'y') } 0..63,
'c' => 'z');
should do the trick ;)
if it is what you want
if you need to add a 'b value' later in the code, you still can do $strings{"b$value"} = 'y'; to add the new value in the hash
I need to convert a given string of numbers to the word those numbers correspond to. For example:
>>>number_to_word ('222 2 333 33')
'CAFE'
The numbers work like they do on a cell phone, you hit once on the second button and you get an 'A', you hit twice and you get an 'B', etc. Let's say I want the letter 'E', I'd have to press the third button twice.
I would like to have some help trying to understand the easiest way to do this function. I have thought on creating a dictionary with the key being the letter and the value being the number, like this:
dic={'A':'2', 'B':'22', 'C':'222', 'D':'3', 'E':'33',etc...}
And then using a 'for' cycle to read all the numbers the in the string, but I do not know how to start.
You need to reverse your dictionary:
def number_to_word(number):
dic = {'2': 'A', '22': 'B', '222': 'C', '3': 'D', '33': 'E', '333': 'F'}
return ''.join(dic[n] for n in number.split())
>>> number_to_word('222 2 333 33')
'CAFE'
Let's start inside out. number.split() splits the text with your number at white space characters:
>>> number = '222 2 333 33'
>>> number.split()
['222', '2', '333', '33']
We use a generator expression ((dic[n] for n in number.split())) to find the letter for each number. Here is a list comprehension that does nearly the same but also shows the result as a list:
>>> [dic[n] for n in number.split()]
['C', 'A', 'F', 'E']
This lets n run through all elements in the list with the numbers and uses n as the key in the dictionary dic to get the corresponding letter.
Finally, we use the method join() with an empty string as spectator to turn the list into a string:
>>> ''.join([dic[n] for n in number.split()])
'CAFE'
I'm trying to implement a hangman game. I want part of the function to check if a letter is correct or incorrect. After a letter is found to be correct it will place the letter in a "used letters" list and a "correct letters list" The correct letters list will be built as the game goes on. I'd like it to sort the list to match the hidden word as the game is going.
For instance let's use the word "hardware"
If someone guessed "e, a, and h" it would come out like
correct = ["e", "a", "h"]
I would like it to sort the list so it would go
correct = ["h", "a", "e"]
then
correct = ["h", "a", "r", "a", "e"] after r has been guessed.
I also need to know if it would also see that "a" is in there twice and place it twice.
My code that doesn't allow you to win but you can lose. It's a work in progress.
I also can't get the letters left counter to work. I've made the code print the list to check if it was adding the letters. it is. So I don't know what's up there.
def hangman():
correct = []
guessed = []
guess = ""
words = ["source", "alpha", "patch", "system"]
sWord = random.choice(words)
wLen = len(sWord)
cLen = len(correct)
remaining = int(wLen - cLen)
print "Welcome to hangman.\n"
print "You've got 3 tries or the guy dies."
turns = 3
while turns > 0:
guess = str(raw_input("Take a guess. >"))
if guess in sWord:
correct.append(guess)
guessed.append(guess)
print "Great!, %d letters left." % remaining
else:
print "Incorrect, this poor guy's life is in your hands."
guessed.append(guess)
turns -= 1
print "You have %d turns left." % turns
if turns == 0:
print "HE'S DEAD AND IT'S ALL YOUR FAULT! ARE YOU HAPPY?"
print "YOU LOST ON PURPOSE, DIDN'T YOU?!"
hangman()
I'm not entirely clear on the desired behavior because:
correct = ["h", "a", "r", "a", "e"] after r has been guessed.
This is strange because a has only been guessed once, but shows up for each time it appears in hardware. Should r should also appear twice? If that is the correct behavior, then a very simple list comprehension can be used:
def result(guesses, key):
print [c for c in key if c in guesses]
In [560]: result('eah', 'hardware')
['h', 'a', 'a', 'e']
In [561]: result('eahr', 'hardware')
['h', 'a', 'r', 'a', 'r', 'e']
Iterate the letters in key and include them if the letter has been used as a "guess".
You can also have it insert a place holder for unfound characters fairly easily by using:
def result(guesses, key):
print [c if c in guesses else '_' for c in key]
print ' '.join([c if c in guesses else '_' for c in key])
In [567]: result('eah', 'hardware')
['h', 'a', '_', '_', '_', 'a', '_', 'e']
h a _ _ _ a _ e
In [568]: result('eahr', 'hardware')
['h', 'a', 'r', '_', '_', 'a', 'r', 'e']
h a r _ _ a r e
In [569]: result('eahrzw12', 'hardware')
['h', 'a', 'r', '_', 'w', 'a', 'r', 'e']
h a r _ w a r e
Can someone please suggest an approach to write the piece of codes that will automatically maps the letter in letter_str onto the dic_key (a dict key string type that contains dashes that match the length of words in word_lst)?
So, the mapping only occurs if a letter appears in every words in the list at the same position no matter how many words is in the list.
If no letter appears at any position for all the words in the word list then the new_dic_key would be '----'. Please see the examples below
Thanks
word_lst = ['ague', 'bute', 'byre', 'came', 'case', 'doze']
dic_key = '----'
letters_str ='abcdefghijklmnopqrstuvwxyz'
new_dic_key = '---e'
if
word_list = ['bute', 'byre']
new_dic_key = 'b--e'
or
word_list = ['drek', 'drew', 'dyes']
new_dic_key = 'd-e-'
If the words in the word_list will be of the same length this code will give what you want:
word_list = ['drek', 'drew', 'dyes']
cols = []
for i in range(len(word_list[0])):
cols.append([])
for word in word_list:
for i, ch in enumerate(word):
cols[i].append(ch)
pattern = [item[0] if len(set(item)) == 1 else '-' for item in cols]
print ''.join(pattern)
d-e-
Explanation:
We initialize cols to be a list of list. It will contain two dimensional representation of the letters in the words of word_list. After populating cols this is what it looks like:
[['d', 'd', 'd'], ['r', 'r', 'y'], ['e', 'e', 'e'], ['k', 'w', 's']]
So the final result new_dic_key will contain the letter only if all elements in the sub-list above have the same letter, otherwise it will contain a -. This is achieved using the list comprehension for pattern.
Hope it helps.
I have the following c++ method:
typedef unsigned long p3tOffsetType;
p3tOffsetType buildString(std::string string)
{
for (stringMap::const_iterator string_iterator = strings.begin(); string_iterator != strings.end(); ++string_iterator)
{
if (string_iterator->second == string)
return string_iterator->first;
}
p3tOffsetType new_string_offset = string_offset;
strings[string_offset] = string;
string_offset += string.size() + 1;
return new_string_offset;
}
What does the function do? I can give more of the code if needed.
The code is a snippet from a P3T file packer found in the source P3TBuilder (version 2.7).
I need to know this because I am trying to
Assuming that strings is a map<p3tOffsetType, std::string> and that string_offset is initialized to zero, it seems to do the following: Imagine that you call the method a few times with, say, "Hello", "Hi", and "Hey", and that you would treat all these strings as C-strings and store them in the same char array. The array elements would then be {'H', 'e', 'l', 'l', 'o', '\0', 'H', 'i', '\0', 'H', 'e', 'y', '\0'}. The starting indices of the three strings are 0, 6, and 9, respectively. What the method does is to create a map that maps these starting indices to the strings, so strings[0] == "Hello", strings[6] == "Hi", and strings[9] == "Hey". Also, it eliminates duplicates, so calling the method again with "Hello" would leave the map unchanged.
It iterates over strings which is a map from p3tOffsetType to string. If the sought after string is found in the map then it returns the offset. If not then it stores the string with the current offset as key and adds the length of the string to the global variable string_offset (which I assume initialized to zero).
Basically, a map of strings and their offsets is built. So if you called it with "Hello", "test" and "bla" it would contain the following:
strings[0] = "Hello"
strings[6] = "test"
strings[11] = "bla"
This keeps track of the strings and where they are located in the "bigger" string, so to speak.