Translating a lambda to a normal function in Python - python

While trying to understand how to use the lambda, I came across one reply in which the poster said that nothing you can do using lambda you can't do using normal functions.
I have been trying so hard to call a function from within itself in Python, not expert though, yet I'm learning, and I came across few problems where you need to use recursive functions, call multiple times to get a certain answer.
A guy has used the lambda function to do that, I tried to understand it but I failed, so I though if the functions can be implemented using normal functions, it would be easier to start understanding the lambda from that point on.
Let's take this sentence for example:
print"\n".join(" ".join([(lambda f:(lambda x:f(lambda*r:x(x)(*r)))(lambda x:f(lambda*r:x(x)(*r))))(lambda f:lambda q,n:len(q)<=n and q or f(q[len(q)/2:],n)+f(q[:len(q)/2],n))(k,z+1)for z,k in enumerate(i[:-1].split())]) for i in list(s)[1:])
This has been used in the Facebook hacker cup, I couldn't solve this problem as I was lost in the loops.
This sentence takes a few words, let's say "Stackoverflow rocks and it is great"
The problem statement in Facebook is :
You've intercepted a series of transmissions encrypted using an interesting and stupid method, which you have managed to decipher. The messages contain only spaces and lowercase English characters, and are encrypted as follows: for all words in a sentence, the ith word (1-based) word is replaced with the word generated by applying the following recursive operation f(word, i):
If the length of word is less than or equal to i,
return word.
Otherwise, return f(right half of word, i) +
f(left half of word, i).
If word is of odd length, it is split such that the right side is longer. You've decided to have a little fun with whoever is sending the messages, and to broadcast your own messages encrypted in the same style that they are using.
Input
Your input will begin with an integer N, followed by a newline and then N test cases. Each case consists of an unencrypted sentence containing only spaces and lowercase letters, and cases are newline-separated. There will be no leading or trailing spaces in a sentence and there will be at most 1 space character between any otherwise-adjacent characters
Output
Output, for each case and separated by newlines, the contents of the encrypted sentence after applying the encoding method describe above to it. You may ignore traditional capitalization rules and stick to all lowercase letters.
Constraints
5 ≤ N ≤ 25
Sentences will contain no more than 100 characters.

Python lambdas are simply syntactic sugar. "Regular" functions have the same capabilities such as closures, because, remember, you can define them inside another function, just as lambda does.
def some_func():
some_expr_using(lambda args: 42)
# becomes:
def some_func():
def unique_name(args):
return 42
some_expr_using(unique_name)
Except that when inspecting the lambda object, its name is set to "<lambda>", rather than unique_name as above, and other superficial details relating to how the actual source code is spelled rather than as it behaves.
Your code could be written as:
def y(f):
def a(x):
def b(*r):
return x(x)(*r)
return f(b)
return a(a)
def fx(f):
def x(q, n):
# changed "a and b or c": different semantics if b can be falsy
if len(q) <= n:
return q
else:
return f(q[len(q) / 2:], n) + f(q[:len(q) / 2], n)
return x
print "\n".join(
" ".join(y(fx)(k, z + 1) for z, k in enumerate(i[:-1].split()))
for i in list(s)[1:])
(But only if I've translated it correctly; double-check. :P)
This code is an example of a fixed-point combinator, which I only barely understand, and it's hard to give better names without knowing more context (I didn't try to decipher the actual problem statement). It can be unraveled to a recursive function which calls itself by name directly.

Related

Trouble with Palindrome function in python

I'm having trouble in an online course for python, specifically a palindrome problem These are the instructions, but the function must be case-insensitive and not see spaces. I think the issue is in my return blocks or my flow. I think I need to use the lower function, but I'm honestly not sure.
def student_func(x):
for string in x:
x.lower()
y = x.replace(" ", "")
if y[::-1]==y:
return True
else:
return False
You actually have two separate problems in your code—and you're right that one of them is with lower and the other is with the return flow.
First, x.lower() doesn't modify x in-place. In fact, strings are immutable; nothing modifies them in-place. If you look up the interactive help or the online docs, it says:
Return a copy of the string with all the cased characters [4] converted to lowercase.
So, you need to do the same thing with lower that you do with replace: assign the result to a variable, and use that:
y = x.lower()
z = y.replace(" ", "")
Or you can reuse the same variable:
x = x.lower()
… or chain the two calls together:
y = x.lower().replace(" ", "")
As a side note, unless you're using Python 2, you should consider whether you want casefold instead of lower. For English it makes no difference, but for other languages it can.
Meanwhile, you're doing for string in x:, but then ignoring string.
If x is just a single word, you don't want to loop over it at all.
If x is a list of words, then the for string in x: is correct, but then you have to use string inside the loop, not x. Plus, you can't just return True or return False—that will exit the function as soon as you test the first word, meaning the rest of them never get tested. I'm not sure whether you want to return True if there are any pallidromes, or if they're all palindromes, or if you want to return a list of booleans instead of a single one, or what, but you can't just return the first one.
It would probably be a lot clearer if you used better names, like words instead of x and word instead of string.
Anyway, I can't tell you the right way to fix this since I don't know what you're trying to do, but hopefully this explains enough that you can fix it yourself.
Giving away the solution defeats the purpose of the exercise
your approach is more or less correct.
convert string to a standard case
remove whitespace
check if reverse of the string is equal to the original string
The error lies in how you are using the python API.
check what each of the functions do, and what they return.
a good idea is to run help(function) to see what the function's documentation has to say about it.
try help(x.lower) (note: not help(x.lower())) and see what the return value is.

Giant set of strings leads to memory error - alternative?

I'm trying to create a really huge list of incrementing 9 digits numbers (worst case). My plan is to have something like this:
['000000001', '000000002' , ..............,'999999999']
I already wrote the code. However, as soon as I run the code, my console prints "Memory Error" message.
Here is my current code:
HUGE_LIST = [''.join(i) for i in product('012345678', repeat = 9)
I know this might not be the best code to produce the list. Thus, can someone help me find a better way to solve this memory issue?
I'm planning to use HUGE_LIST for comparison with user input.
Example: a user enters '12345678' as input, then I want my code to assert that input with the HUGE_LIST.
The best way to solve an issue like this is to avoid a memory-intensive algorithm entirely. In this case, since your goal is to test whether a particular string is in the list, just write a function that checks whether the string satisfies the criteria to be in the list. For example, if your list contains all sequences of 9 digits, then your function just has to check whether a given input is a sequence of 9 digits.
def check(string):
return len(string) == 9 and all(c.isdigit() for c in string)
(in practice, give it a better name than check). Or if you want all sequences of 9 digits in which none of them is a 9, as your current code defining HUGE_LIST suggests, you could write
def check(string):
return len(string) == 9 and all(c.isdigit() and c != '9' for c in string)
Or so on.
If you can't write an algorithm to decide whether a string (or whatever) is in the list or not, the next best thing is to make a generator that will produce the values one at a time. If you already have a list comprehension, like
HUGE_LIST = [<something> for <variable> in <expression>]
then you can turn that into a generator by replacing the square brackets with parentheses:
HUGE_GENERATOR = (<something> for <variable> in <expression>)
Then you can test for membership using string in HUGE_GENERATOR. Note that after doing so, HUGE_GENERATOR will be (at least partially) consumed, so you can't use it for another membership test; you will have to recreate it if you want to test again.

Pretty-print Lisp using Python

Is there a way to pretty-print Lisp-style code string (in other words, a bunch of balanced parentheses and text within) in Python without re-inventing a wheel?
Short answer
I think a reasonable approach, if you can, is to generate Python lists or custom objects instead of strings and use the pprint module, as suggested by #saulspatz.
Long answer
The whole question look like an instance of an XY-problem. Why? because you are using Python (why not Lisp?) to manipulate strings (why not data-structures?) representing generated Lisp-style code, where Lisp-style is defined as "a bunch of parentheses and text within".
To the question "how to pretty-print?", I would thus respond "I wouldn't start from here!".
The best way to not reinvent the wheel in your case, apart from using existing wheels, is to stick to a simple output format.
But first of all all, why do you need to pretty-print? who will look at the resulting code?
Depending on the exact Lisp dialect you are using and the intended usage of the code, you could format your code very differently. Think about newlines, indentation and maximum width of your text, for example. The Common Lisp pretty-printer is particulary evolved and I doubt you want to have the same level of configurability.
If you used Lisp, a simple call to pprint would solve your problem, but you are using Python, so stick with the most reasonable output for the moment because pretty-printing is a can of worms.
If your code is intended for human readers, please:
don't put closing parenthesis on their own lines
don't vertically align open and close parenthesis
don't add spaces between opening parenthesis
This is ugly:
( * ( + 3 x )
(f
x
y
)
)
This is better:
(* (+ 3 x)
(f x y))
Or simply:
(* (+ 3 x) (f x y))
See here for more details.
But before printing, you have to parse your input string and make sure it is well-formed. Maybe you are sure it is well-formed, due to how you generate your forms, but I'd argue that the printer should ignore that and not make too many assumptions. If you passed the pretty-printer an AST represented by Python objects instead of just strings, this would be easier, as suggested in comments. You could build a data-structure or custom classes and use the pprint (python) module. That, as said above, seems to be the way to go in your case, if you can change how you generate your Lisp-style code.
With strings, you are supposed to handle any possible input and reject invalid ones.
This means checking that parenthesis and quotes are balanced (beware of escape characters), etc.
Actually, you don't need to really build an intermediate tree for printing (though it would probably help for other parts of your program), because Lisp-style code is made of forms that are easily nested and use a prefix notation: you can scan your input string from left-to-right and print as required when seeing parenthesis (open parenthesis: recurse; close parenthesis, return from recursion). When you first encounter an unescaped double-quote ", read until the next one ", ...
This, coupled with a simple printing method, could be sufficient for your needs.
I think the easiest method would be to use triple quotations. If you say:
print """
(((This is some lisp code))) """
It should work.
You can format your code any way you like within the triple quotes and it will come out the way you want it to.
Best of luck and happy coding!
I made this rudimentary pretty printer once for prettifying CLIPS, which is based on Lisp. Might help:
def clips_pprint(clips_str: str) -> str:
"""Pretty-prints a CLIPS string.
Indents a CLIPS string for easier visual confirmation during development
and verification.
Assumes the CLIPS string is valid CLIPS, i.e. braces are paired.
"""
LB = "("
RB = ")"
TAB = " " * 4
formatted_clips_str = ""
tab_count = 0
for c in clips_str:
if c == LB:
formatted_clips_str += os.linesep
for _i in range(tab_count):
formatted_clips_str += TAB
tab_count += 1
elif c == RB:
tab_count -= 1
formatted_clips_str += c
return formatted_clips_str.strip()

Python Small Ubbi Project

Hello everyone I've been practicing with python for a bit now and found a project named Ubbi. Pretty much the whole goal is, is to add a string 'ub' before every vowel. So my question am i even close to cracking this or should i head another route??
def ubbidubbi_word(eword):
ubword = ""
for i in eword:
if i == 'aeoiuy': ubword += 'ub'+eword(i)
else: ubword += eword(i)
return ubword
You're close! However...:
(A) eword(i) would call eword as a function with argument i, which makes no sense; just use i itself, the character you're currently looking at (maybe you're thinking of Javascript here...? but even there the syntax will be different);
(B) i, a single character, will never equal the string 'aeoiuy', as you're checking; rather you should check if i is in that string (and thus a vowel).

How to split a string of Python source code into Python "statements"?

Given a string s containing (syntactically valid) Python source code, how can I split s into an array whose elements are the strings corresponding to the Python "statements" in s?
I put scare-quotes around "statements" because this term does not capture exactly what I'm looking for. Rather than trying to come up with a more accurate wording, here's an example. Compare the following two ipython interactions:
In [1]: if 1 > 0:
......: pass
......:
In [2]: if 1 > 0
File "<ipython-input-1082-0b411f095922>", line 1
if 1 > 0
^
SyntaxError: invalid syntax
In the first interaction, after the first [RETURN] statement, ipython processes the input if 1 > 0: without objection, even though it is still incomplete (i.e. it is not a full Python statement). In contrast, in the second interaction, the input is not only incomplete (in this sense), but also not acceptable to ipython.
As a second, more complete example, suppose the file foo.py contains the following Python source code:
def print_vertically(s):
'''A pretty useless procedure.
Prints the characters in its argument one per line.
'''
for c in s:
print c
greeting = ('hello '
'world'.
upper())
print_vertically(greeting)
Now, if I ran the following snippet, featuring the desired split_python_source function:
src = open('foo.py').read()
for i, s in enumerate(split_python_source(src)):
print '%d. >>>%s<<<' % (i, s)
the output would look like this:
0. >>>def print_vertically(s):<<<
1. >>> '''A pretty useless procedure.
Prints the characters in its argument one per line.
'''<<<
2. >>> for c in s:<<<
3. >>> print c<<<
4. >>>greeting = ('hello '
'world'.
upper())<<<
5. >>>print_vertically(greeting)<<<
As you can see, in this splitting, for c in s: (for example) gets assigned to its own item, rather being part of some "compound statement."
In fact, I don't have a very precise specification for how the splitting should be done, as long as it is done "at the joints" (like ipython does).
I'm not familiar with the internals of the Python lexer (though almost certainly many people on SO are :), but my guess is that you're basically looking for lines, with one important exception : paired open-close delimiters that can span multiple lines.
As a quick and dirty first pass, you might be able to start with something that splits a piece of code on newlines, and then you could merge successive lines that are found to contain paired delimiters -- parentheses (), braces {}, brackets [], and quotes '', ''' ''' are the ones that come to mind.

Categories

Resources