#esoteric-python
1 messages ยท Page 73 of 1
but actually I'm still not sure if that solves it? cause it depends on the cache return value
ah yes with a more complex syntax that works
in the meantime, the closest I've got to is
This could be useful:
https://github.com/rfk/withhacks May be up your alley too, specifically https://billmill.org/multi_line_lambdas.html
is there anything that allows me to do
with obj:
pass
i.e. without a function call?
Yes, provided you initialize the context manager beforehand
oh I can just make an object with __enter__ and __exit__
I guess that's what the contextlib builds
!e ```python
import sys
class SkipWithBlock(Exception):
pass
class SkipContextManager:
def init(self, skip):
self.skip = skip
def __enter__(self):
if self.skip:
sys.settrace(lambda *args, **keys: None)
frame = sys._getframe(1)
frame.f_trace = self.trace
def trace(self, frame, event, arg):
raise SkipWithBlock()
def __exit__(self, type, value, traceback):
if type is None:
return # No exception
if issubclass(type, SkipWithBlock):
return True # Suppress special SkipWithBlock exception
cm = SkipContextManager(skip=True)
with cm:
print('In the with block') # Won't be called
print('Out of the with block')
@distant wave Your eval job has completed.
Out of the with block
Uses the same set_trace hack
excellent, I've saved myself 2 more characters
LOL I forgot my other requirement that I also need to write to the cache
blargh this is futile
Watch this
!e ```python
class Cached:
def init(self, value):
self.value = value
def set(self, value):
self.value = value
def get(self, value):
return self.value
def call(self):
return self.value
a = Cached(2)
print(a)
a = 2
print(a)
print(a())
@distant wave Your eval job has completed.
001 | <__main__.Cached object at 0x7fa7c5c16ef0>
002 | 2
003 | Traceback (most recent call last):
004 | File "<string>", line 19, in <module>
005 | TypeError: 'int' object is not callable
bleh
lol I was just looking into overriding assignments
Not sure exactly what I did wrong
that's supposed to be a descriptor
Ah
it doesn't work in the global namespace
Usually it's best to just put the acquisition code in a function, and wrap it in a caching decorator
time for
if key not in cache:
cache[key] = logic()
y = cache[key]
my usecase it sort of the opposite: the acquisition code is highly variable, so it needs to be defined on the fly
Ah
I could write it in an inline function, but I hate those : (
You can use a class as a decorator expreesion.
Like @class
Or any expression whose result is callable.
technically you can also use an expression whose result is not callable
>>> def weird_decorator(func):
... func()
... return 42
...
>>> @weird_decorator
... def something():
... print('hello')
...
hello
>>> something
42```
Hmmm```python
@hash
... def hello(): pass
...
hello
-9223363277273818689```
You can't put a lambda up there unfortunately (unless it's in a variable).
Incidentally, this gives me an idea for a horrible piece of obfuscated code I might someday write.
technically you can also use an expression whose result is not callable
I meant that a thing right after @ should be callable.
!e
Sorry, but you may only use this command within #bot-commands.
@brisk zenith i used your list __getitem__ replacement code to implement BF using list slicing. would that be a valid submission for challenge 3?
ooh how does it look?
i didnt have to make a seperate class, but it made it easier for debugging. ill prob move it all into list
i did use my golfed bf interpreter from a bit back tbh
ohh i see, so it behaves like BF but has different syntax. interesting! yeah sure, i reckon that's acceptable for the challenge (mostly for the interesting implementation) :D
aight
im gonna move all the logic into list.__getitem__ and then ill test and submit
This implements the classic BF language using lists and slicing on the list class
[][
[[]]::[[]] # starts bf program
][
[]:[]:[] # equivalent to ","
][
[] # equivalent to "."
][
[[]] # runs the program
]
the above program takes in one character and outputs it.
other implemented commands are:
:[]:[] # which is ">"
[]:[]: # which is "<"
[]::[] # which is "+"
:[]: # which is "-"
[]:: # which is "["
::[] # which is "]"
@brisk zenith it breaks help() somehow
yeah messing with builtins with ctypes can do all sorts of unexpected things
@brisk zenith whats the best way to find the ptr ro an int mrethod? im tring to get the int.__xor__ method to replace it
if i remember correctly, you get a c_ssize_t at 96 bytes after the address of int, then use the value of that plus 112 to get the function pointer of __xor__
similar to my list getitem replacement except it's a different method in a different place
no problem. the numbers may be wrong though, but give it a go and refer to the py type struct in the cpython code if it's wrong
thats where to look? awesome
@brisk zenith do you think its possible to make tuples mutable with ctypes so they work like this? ```py
x = (0,1,2)
x[0] = 1
@rugged sparrow probably
yes, i think it's possible.
in fact, i don't see why it definitely should be possible
if you handle reference counts and all that properly, it may even be perfectly stable
mutable tuple is called a list
not necessarily
yeah ๐
a list can have its size changed, a tuple cannot so easily without causing some pretty funky problems
I mean yeah that was me not understanding stuff in the past
oh i see :D
(1,2,3).append(4)
Haha, I would love if append accepted multiple arguments
So a = [1,2,3]; a.append(4,5) would be a thing
a.extend([4, 5])
Yeah but
@marsh void you can replace list.append but it may be tricky
>>> list_dict = py_object.from_address(id(list.__dict__)+16).value
>>> list_dict['append']
<method 'append' of 'list' objects>
>>> list_dict['append'] = lambda self,*args:self.extend(args)
>>> a = [0,1,2]
>>> a.append
<built-in method append of list object at 0x7e24f6a2f888>
>>> a.append(1,2)
Segmentation fault (core dumped)``` however this doesnt work as expected
wonder when a seg fault is the expected and wanted behaviour ๐
rarely lmao
>>> a = 1
>>> list_dict['append'] = a
>>> list_dict['append']
1
>>> list_dict['append']
1
>>> [].append
<set_iterator object at 0x785608fd9288>``` huh
what's in this mysterious set iterator object? can you get values from it without a segfault?
https://github.com/NeKitDS/gd.py/blob/master/gd/utils/wrap_tools.py#L80-L91 Using this (idk why I had put this in my library)
@new_method(list)
def append(self, *args):
for arg in args:
self += [arg]
I think this should work
Yeah, new_method is a thing chilaxan had posted before, but wraps a function
@sick hound I'll test in like 5
Oh yeah, segfault in mine too xd
>>> from ctypes import *
>>> list_dict = py_object.from_address(id(list.__dict__)+16).value
>>> a = []
>>> a.append
<built-in method append of list object at 0x7e6fa4d6c808>
>>> list_dict['append'] = 1
>>> a.append
<set_iterator object at 0x7e6fa5eec288>
>>> x = a.append
>>> x
Segmentation fault (core dumped)``` @sick hound
last time you did a = 1; list_dict['append'] = a
not sure if that makes a difference though
>>> from ctypes import *
>>> list_dict = py_object.from_address(id(list.__dict__)+16).value
>>> a = 1
>>> list_dict['append'] = a
>>> list.append
<set_iterator object at 0x7d4b0e553288>
Segmentation fault (core dumped)``` seems to be random
>>> type(list.append)
<class 'method_descriptor'>
>>> type(list().append)
<class 'builtin_function_or_method'>
>>> ``` @sick hound this could be part of the reason
@sick hound figured it out
when the original append method gets deallocated shit starts to fuck up
oh
>>> from ctypes import *
>>> a = py_object.from_address(id(list.__dict__)+16).value['append']
>>> py_object.from_address(id(list.__dict__)+16).value['append'] = lambda self,*args:self.extend(args)
>>> b = []
>>> b.append
<built-in method append of list object at 0x7d7a7569c8c8>
>>> b.append()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: append() takes exactly one argument (0 given)
>>> b.append(1)
>>> b
[1]
>>> b.append(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: append() takes exactly one argument (2 given)
>>> ``` cause this
this is just weird actually
chronos@localhost ~ $ python
Python 3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *;py_object.from_address(id(list.__dict__)+16).value['append'] = lambda self,*args:self.extend(args)
>>> a = []
>>> a.append(0,1,2)
Segmentation fault (core dumped)
chronos@localhost ~ $ python
Python 3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *;py_object.from_address(id(list.__dict__)+16).value['append'] = lambda self,*args:self.extend(args)
>>> a = []
>>> a.append(0,1,2)
>>> a
[0, 1, 2]
>>> ``` @sick hound lets play a fun game called schodingers segfault
it works sometimes
other times it segfaults
>>> list.append
<built-in function write>```
also that happens sometimes (then it segfaults)
no clue
chronos@localhost ~ $ python
Python 3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *;py_object.from_address(id(list.__dict__)+16).value['append'] = lambda self,*args:self.extend(args)
>>> list.append
<function <lambda> at 0x78ac211a2730>
>>> list().append
<bound method <lambda> of []>
>>> ``` and sometimes it works
idk why its random tho
that may need something like gdb lmao
@brisk zenith you might want to look at this too ^
only if we could
while True:
try:
list.append(1, 2, 3)
except SegmentationFault:
pass
๐
๐ค
@sick hound I figured it out I believe. I think the lambda was being deallocated
welp nevermind
that wasnt it
def new_method(cls):
def func_dec(func):
from ctypes import py_object,c_size_t,sizeof
cls_dict = py_object.from_address(id(cls.__dict__) + sizeof(c_size_t) * 2).value
cls_dict[func.__name__] = func
return func_dec``` my decorator didnt work either (as expected lol)
Haha I have actually started this all ๐
Let's just do it with appendmany?
discord_server_start_date = lambda d: __import__("datetime").datetime.utcfromtimestamp((int(str(bin(int(d)))[2:].zfill(2**6)[:42],2)+1.4200704e12)/1e3).strftime('%Y-%m-%d %H:%M:%S')
does it get any more beautiful?
@grizzled cloak what does that do?
converts a discord servers id into when it was created
someone aksed about it in #python-discussion so i had to implement it
oh thats cool
they posted this picture on how it works
http://i.imgur.com/UxWvdYD.png
and well when you can save 1 char you have to:
1000 -> 1e3
or
1420070400000 -> 1.4200704e14
im pretty proud of it because its the first "esoteric" thing ive done that actually does anything
!e
print(discord_server_start_date(267624335836053506))```
Sorry, but you may only use this command within #bot-commands.
whaaat not even here?
well this is a shorter and updated version:
discord_server_start_date=lambda d: __import__("datetime").datetime.utcfromtimestamp((int(f'{d:b}'.zfill(64)[:42],2)+1.4200704e12)/1e3).strftime('%Y-%m-%d %H:%M:%S')
print(discord_server_start_date(267624335836053506))```
Fstring-ception
if I could jsut drop the > it'd also be shorter ๐
you should be able to just nest brackets
>>> f'{{10:b}:0>64}'
File "<stdin>", line 1
SyntaxError: f-string: single '}' is not allowed``` @zealous widget
i've nested brackets before hmm:
f'{"hi":>{30 - 20}}'
' hi'
hmm
guess it depends on the side
yea
when I put it on the left it wants to assign a variable to b
what are some fun esoteric challenges?
maybe something that focuses on efficiency
@grizzled cloak golf tictactoe
Haha, this one is mhh
https://github.com/NeKitDS/python_scripts/blob/master/rps/rps.py I think this is my Rock Paper Scissors short implementation
Idk why did I post it here though, I since it isn't real golfing
isnt golfing writing it in as few chars as possible?
Yeah
depends, is it for two players or does the computer play one side
Just try to golf it
i'd just pick random moves for a computer player
See how low you can go
How about a nice game of chess?
isnt that from wargames?
yep
very good movie
can i get from this:
[
0, 1, 2,
3, 4, 5,
6, 7, 8
]```
to this:
```py
[
2, 5, 8,
1, 4, 7,
0, 3, 6
]```
its a numpy array
but its 1D
and i want to rotate it by 90degrees to the left
i guess i can use a 2d list instead
that'd be a lot easier for the rotating
probably, but import numpy will count as characters used
i'd translate player moves into value from a magic square so it's easy to check if they have 3-in-a-row
2 | 7 | 6
9 | 5 | 1
4 | 3 | 8
notice the rows, columns, and diagonals all add to 15
so you can just check if 3 of the players moves add to 15
what do you mean? that was an original thought by me
magic squares are pretty common but never would've though about them for tictactoe ๐
first time ive heard of them
i wouldn't use numpy, but i might use itertools.combinations
type(np.NaN)
Out[85]: float```
hmmm
unless you wanted to use numpy just for pretty printing the array
apart from getting to know the suqares in school I bumped into a few challenges for python regarding htem
generating magic squares would be a challenge in itself
so how many chars would you say would a solution using magic squares use?
i dunno, that just seems like the fastest way to check 3 in a row
might be a better way
i first thought of importing networkx and using a grid-graph, but that solution would be long
Must it be -1?
well i had my board be 1 for player1, 0 for nothing and -1 for player2
that way i could invert my board by multiplying it with -1
some un-golfed psuedo-code:
from itertools import combinations
moves = {"a1" : 2,
"a2" : 7,
"a3" : 6,
"b1" : 9,
"b2" : 5,
"b3" : 1,
"c1" : 4,
"c2" : 3,
"c3" : 8}
player1_moves = []
player2_moves = []
while True:
get_input() #check that input is valid
playerx_moves.append(moves[user_input])
del moves[user_input]
if any([sum(combination) == 15
for combination in combinations(playerx_moves, 3)]):
winner()
draw()
need to fix that if statement, but you get the point
lambda b: any([all(b[0]), all(b[1]), all(b[2]), all(np.diag(b))]) was my way of checking for a win
then by turning the board by 90 degrees you could check vertical and the other diagonal
array[::-1].T
hm?
that's how you turn it 90 degrees
>>> a = np.arange(25).reshape([5,5])
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
>>> a[::-1].T
array([[20, 15, 10, 5, 0],
[21, 16, 11, 6, 1],
[22, 17, 12, 7, 2],
[23, 18, 13, 8, 3],
[24, 19, 14, 9, 4]])
just be mindful of which way it rotates
hmmmm
b
Out[120]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
b.diagonal()
Out[121]: array([0, 4, 8])
np.rot90(b).diagonal()
Out[122]: array([2, 4, 6])```
but it would have worked to get the diagonals
shouldn't matter if they're only checking for the square
i feel like magic square is better than this
yeah probably but i didnt know they existed
still ungolfed and doesn't print the grid, but functional:
from itertools import combinations
moves = {"a1" : 2,
"a2" : 7,
"a3" : 6,
"b1" : 9,
"b2" : 5,
"b3" : 1,
"c1" : 4,
"c2" : 3,
"c3" : 8}
player1_moves = []
player2_moves = []
p_moves = [player1_moves, player2_moves]
player = False
while True:
while True:
in_ = input(f"Player {player + 1} move: ")
if in_ in moves:
break
else:
print("Not a legal move.\n")
if player:
player2_moves.append(moves[in_])
else:
player1_moves.append(moves[in_])
del moves[in_]
if any([sum(combination) == 15
for combination in combinations(p_moves[player], 3)]):
print(f"Player {player + 1} wins!")
break
if not moves:
print(f"It's a draw!")
player = not player
Player 1 move: a1
Player 2 move: a2
Player 1 move: b1
Player 2 move: a3
Player 1 move: c1
Player 1 wins!
can you shorten any of that logic though?
the error checking isn't working for some reason
"error catching"
im still having some problems with my inline if statements...
sort of golfed with no catching bad moves, program just crashes:
from itertools import combinations as c
m={"a1":2,"a2":7,"a3":6,"b1":9,"b2":5,"b3":1,"c1":4,"c2":3,"c3":8};p=[[],[]];q=0
while m:
i=input(f"P{q+1} move: ");p[q]+=[m[i]];del m[i]
if any([sum(d)==15 for d in c(p[q], 3)]):print(f'P{q+1} wins');break
if not m:print(f"Draw")
q=not q
i dont think i can beat this
my invert lambda already looks like this:
invert = lambda b: np.array(list(map(lambda x: not x if type(x) is bool else x, b.flatten()))).reshape(3,3)```
that's a hell of a function
ok i guess replacing map with a list comp saves a bit of space
invert = lambda b: np.array([not x if type(x)==bool else x for x in b.flatten()]).reshape(3,3)```
all because -1 is seen as True
and the ~ operator cant just skip over stuff it cant invert
hsogjhho
could shorten it more by changing the text and the grid names i suppose
i dunno how to improve the logic of it though
yay! these couple of lambdas will tell you who won.
won = lambda b: any([all(b[0]), all(b[1]), all(b[2]), all(np.diag(b))])
invert = lambda b: np.array([not x if type(x)==bool else x for x in b.flatten()]).reshape(3,3)
did_win = lambda board: True if won(board) or won(np.rot90(board)) else (False if (won(invert(board)) or won(np.rot90(invert(board)))) else None)```
callable on a board such as:
s5 = np.array([
[False, True, None],
[True, False, None],
[True, None, False]
])```
results in False
(player2 won)
and None if its a tie
True if player 1 wins
@zealous widget how many chars is yours?
ah found yours. 294
well.
import numpy as np;w=lambda b: any([all(b[0]),all(b[1]),all(b[2]),all(np.diag(b))]);i=lambda b: np.array([not x if type(x)==bool else x for x in b.flatten()]).reshape(3,3);k=lambda b: 1 if w(b) or w(np.rot90(b)) else (2 if (w(i(b)) or w(np.rot90(i(b)))) else None);p=False;b=np.ndarray((3,3),dtype=type(None));print(b)
while k(b)==None:
m=int(input());p=not p;_=divmod(m,3)
if 0<=m<=8 and b[_]==None: b[_]=p
else: p=not p
print(b)
print(p," wins")```
i guess 463 is the best i got
from itertools import combinations as c
m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0
h="โโโโผโโโโผโโโ";b = [" 0 โ 1 โ 2 ",h," 3 โ 4 โ 5 ",h," 6 โ 7 โ 8 \n"];b=[list(s) for s in b]
while m:
print('\n'.join(''.join(s) for s in b))
i=int(input(f"P{q+1} move: "));p[q]+=[m[i]];del m[i]
b[2*(i//3)][(4*(i%3))+1]='O'if q else 'X'
if any([sum(d)==15 for d in c(p[q], 3)]):print(f'P{q+1} wins');break
if not m:print(f"Draw")
q=not q
this version has a board
technically i could make the board smaller
@zealous widget q=not q, but why not q^=1?
Since you don't need the booleans I can see
probably works
it's not working
just keeps player 1 constantly, i need to switch between them
q is the current player
mhm so 0 is 1 and 1 is 2?
yeah
>>> 0^0
0
^1
just stays at player1
oh, i had q^=q
Lmao
from itertools import combinations as c
m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0
h="โโผโโผโ";b = ["0โ1โ2",h,"3โ4โ5",h,"6โ7โ8"];b=[list(s) for s in b]
while m:
print('\n'.join(''.join(s) for s in b))
i=int(input(f"P{q+1} move: "));p[q]+=[m[i]];del m[i]
b[2*(i//3)][2*(i%3)]='O'if q else 'X'
if any([sum(d)==15 for d in c(p[q],3)]):print(f'P{q+1} wins');break
if not m:print(f"Draw")
q^=1
shrank the board
i had the squares labeled 1 through 9, but then the list indexing math had an extra -1 in it so i figured i'd shorten it
not my fault if your terminal font sucks!
i'm not sure what i'm using, i think just ubunto mono --- it doesn't differentiate between 0 and O very well either
overwrites = {
ctx.guild.default_role: PermissionOverwrite(read_messages=False),
ctx.guild.me: PermissionOverwrite(read_messages=True, send_messages=True),
for member in tts[0]['allowed_members']:
member: PermissionOverwrite(read_messages=True, send_messages=True)
}
``` can I do something like this?
i mean this is not working ;v
why in esoteric?
Yeah
rip
im just asking about syntax
if you can comp that dict, i'd be impressed
or you talking to style
can't you use a string 276951438 instead of the dict {0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8} if you're trying to golf it?
you're right, i can
good point, ever since i changed the grid names, just indexing a string would work
although you'll have to put an int() everytime you reference it, so it might not save bytes
you could use list() around that string
but that might not save bytes then
then it'll suport del
the list shrinking is ruining my indexing
rip
can i do a dict comp with the string that saves bytes
{i:c for i,c in enumerate('276951438')} doesn't reallly seem like it saves anymore
it might, gotta count it
>>> something = [1,2,3,4,5]
>>> thing = False
>>> {'a': True, 'b': False, **{member: thing for member in something}}
{'a': True, 'b': False, 1: False, 2: False, 3: False, 4: False, 5: False}
``` so this is a thing about Style's question
But using objects as dict keys isn't the best idea tbh
(I mean, user-created objects)
don't they need to be hashable
i could still use a string if i change the internal logic a bit
from itertools import combinations as c
m="276951438";p=[[],[]];q=0
h="โโผโโผโ";b=["0โ1โ2",h,"3โ4โ5",h,"6โ7โ8"];b=[list(s) for s in b]
while 1:
print('\n'.join(''.join(s) for s in b))
i=int(input(f"P{q+1} move: "));p[q]+=[int(m[i])]
b[2*(i//3)][2*(i%3)]='O'if q else 'X'
if any([sum(d)==15 for d in c(p[q],3)]):print(f'P{q+1} wins');break
if len(p[q])>4:print(f"Draw");break
q^=1
functional, but doesn't error or anything for incorrect moves
Ha! For only 2x the chars you can have error handling!
not even 2x, it's like 6 extra characters or something
No I mean in my version hahaha
ah, oof
Oh man magic squares was really the way to go
But I do find mine more esoteric/unreadable
yeah, numpy is overkill
print(['No One','X','O'][(lambda x=(lambda f:[f()for _ in range(9)])(lambda b=[*range(9)],u=[' ']*9,f=[0,1]:[(lambda p:[p(u),p(b)])(lambda a,p=print:[p('_'*7),[p('\x1b[4m',*a[x:x+3],'\x1b[0m',sep='|')for x in[0,3,6]]]),(lambda i:[u.pop(i),u.insert(i,'XO'[f[1]-1])])((lambda c=[0]:[c.pop(),[_ for _ in iter(lambda:(lambda i=input('XO'[f[1]-1]+':'):0if i not in'012345678'or len(i)==0else[c.append(int(i)),1][1]if int(i)in range(8)and' '==u[int(i)]else 0)(),1)],c[0]][2])()),(lambda:[f.pop(0),f.insert(0,f[0])]if 1in[all([u[int(x)]=='XO'[f[1]-1]for x in str(*map(ord,'รลสฆษถฦกฤอรถ'),[y])])for y in range(8)]else 0)(),f.append([0,2,1][f.pop(1)])]if 0==f[0]else f[0]):0if x[8]not in[1,2]else x[8])()],'Wins')``` so i just got home this is one i have from a while back
How many chars is that?
too many
Could you check?
looks like a lot
but it has a cool looking board (run in a unix style term) and error handling
and tie game handling
its also a single line
lol
it's throwing an error whenever i try to input anything
...
else 0)(),1)],c[0]][2])()),(lambda:[f.pop(0),f.insert(0,f[0])]if 1in[all([u[int(x)]=='XO'[f[1]-1]for x in str(*map(ord,'รลสฆษถฦกฤอรถ'),[y])])for y in range(8)]else 0)(),f.append([0,2,1][f.pop(1)])]if 0==f[0]else f[0]):0if x[8]not in[1,2]else x[8])()],'Wins')
File "/home/salt/Documents/Python/discord/tictactoe.py", line 26, in <listcomp>
print(['No One','X','O'][(lambda x=(lambda f:[f()for _ in range(9)])(lambda b=[*range(9)],u=[' ']*9,f=[0,1]:[(lambda p:[p(u),p(b)])(lambda a,p=print:[p('_'*7),[p('\x1b[4m',*a[x:x+3],'\x1b[0m',sep='|')for x in[0,3,6]]]),(lambda i:[u.pop(i),u.insert(i,'XO'[f[1]-1])])((lambda c=[0]:[c.pop(),[_ for _ in iter(lambda:(lambda i=input('XO'[f[1]-1]+':'):0if i not in'012345678'or len(i)==0else[c.append(int(i)),1][1]if int(i)in range(8)and' '==u[int(i)]else 0)(),1)],c[0]][2])()),(lambda:[f.pop(0),f.insert(0,f[0])]if 1in[all([u[int(x)]=='XO'[f[1]-1]for x in str(*map(ord,'รลสฆษถฦกฤอรถ'),[y])])for y in range(8)]else 0)(),f.append([0,2,1][f.pop(1)])]if 0==f[0]else f[0]):0if x[8]not in[1,2]else x[8])()],'Wins')
TypeError: str() takes at most 3 arguments (9 given)
>>>
yea its prob broken
print(['No One','X','O'][(lambda x=(lambda f:[f()for _ in range(9)])(lambda b=[*range(9)],u=[' ']*9,f=[0,1]:[(lambda p:[p(u),p(b)])(lambda a,p=print:[p('_'*7),[p('\x1b[4m',*a[x:x+3],'\x1b[0m',sep='|')for x in[0,3,6]]]),(lambda i:[u.pop(i),u.insert(i,'XO'[f[1]-1])])((lambda c=[0]:[c.pop(),[_ for _ in iter(lambda:(lambda i=input('XO'[f[1]-1]+':'):0if i not in'012345678'or len(i)==0else[c.append(int(i)),1][1]if int(i)in range(8)and' '==u[int(i)]else 0)(),1)],c[0]][2])()),(lambda:[f.pop(0),f.insert(0,f[0])]if 1in[all([u[int(x)]=='XO'[f[1]-1]for x in str([*map(ord,'รลสฆษถฦกฤอรถ')][y])])for y in range(8)]else 0)(),f.append([0,2,1][f.pop(1)])]if 0==f[0]else f[0]):0if x[8]not in[1,2]else x[8])()],'Wins')
``` @zealous widget fixed it
added a few bytes, but now it works with the numpad better:
from itertools import combinations as c
m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0
h="โโผโโผโ";b=["7โ8โ9",h,"4โ5โ6",h,"1โ2โ3"];b=[*map(list,b)]
while m:
print('\n'.join(''.join(s) for s in b))
i=int(input(f"P{q+1} move: "))-1;p[q]+=[m[i]];del m[i]
b[-1-2*(i//3)][2*(i%3)]='O'if q else 'X'
if any([sum(d)==15 for d in c(p[q],3)]):print(f'P{q+1} wins');break
if not m:print(f"Draw")
q^=1
looks like:
7โ8โ9
โโผโโผโ
4โ5โ6
โโผโโผโ
1โ2โ3
P1 move: 5
7โ8โ9
โโผโโผโ
4โXโ6
โโผโโผโ
1โ2โ3
P2 move: 9
7โ8โO
โโผโโผโ
4โXโ6
โโผโโผโ
1โ2โ3
P1 move:
If there are many maps, prints or ranges, you can reduce the amount of characters by storing them as one-character variables.
yes
willdo
max([c for c in[0,1,2]if 1in[all([c==b[int(i)]for i in"%s"%ord(s)])for s in'อฌศรษถหฅออส']])```
^ for checking my board
i dunno what it's doing
(lambda p:(p(1),p(2),p(3)))(print)
# if you want to insert it in a single expression
q=print;q(6) # if you want a single line
getting the max ๐
yeah, but how is getting the max checking the board? whats happening under the hood
i understand the magic square thing cause i thought of it
from looking at the string at the end, I don't want to know what it's doing ๐
import itertools as c
m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0;r=print;h="โโผโโผโ";b=["7โ8โ9",h,"4โ5โ6",h,"1โ2โ3"];b=[*map(list,b)]
while m:
r('\n'.join(''.join(s)for s in b));i=int(input(f"P{q+1} move: "))-1;p[q]+=[m[i]];del m[i];b[-1-2*(i//3)][2*(i%3)]='XO'[q]
if any([sum(d)==15for d in c.combinations(p[q],3)]):r(f'P{q+1} wins');break
if not m:r(f"Draw")
q^=1
other than re-indexing, are there any other obvious saves
i can group up some statements on one line and remove some spaces i think
is it looking more golf-y?
maybe turn 4 spaces into 1?
oh yeah
Are you using c only once?
yep
15 for -> 15for
else'x'
'O'if q else 'X' ->'XO'[q]
that's a good one
(''.join(s)for s in b) -> map(''.join,b)
You make sure that everything works after every change, right?
Cause I can be dumb
(or just not considering some cases)
i'm doing light testing
not all cases tested though
import itertools as c
m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0;r=print;h="โโผโโผโ";b=["7โ8โ9",h,"4โ5โ6",h,"1โ2โ3"];b=[*map(list,b)]
while m:
r('\n'.join(map(''.join,b)));i=int(input(f"P{q+1} move: "))-1;p[q]+=[m[i]];del m[i];b[-1-2*(i//3)][2*(i%3)]='XO'[q]
if any([sum(d)==15for d in c.combinations(p[q],3)]):r(f'P{q+1} wins');m=0
elif not m:r(f"Draw")
q^=1
current
i doubt there's a good comp for m --- maybe though
might have to read the wiki article on magic squares
Oh Is m the magic sqr?
2*(i%3)
i%3<<1
single char, but still
oh is that byte shifting?
Yeah, bit shifting
oops, but
bit
rip typing
we can do it twice
have two 2*s
oh, i don't know how far it binds
Why are you using a dict if they keys are 0-8?
because i delete items (so can't use string) and i depend on the indexing not changing when that happens
(indexing can't change)
Ah
right
i have a string version that saves a few characters, but it doesn't catch wrong moves
and i think it's worth crashing for wrong moves
yeah, that's what the string version does
from itertools import combinations as c
m="276951438";p=[[],[]];q=0
h="โโผโโผโ";b=["0โ1โ2",h,"3โ4โ5",h,"6โ7โ8"];b=[list(s) for s in b]
while 1:
print('\n'.join(''.join(s) for s in b))
i=int(input(f"P{q+1} move: "));p[q]+=[int(m[i])]
b[2*(i//3)][2*(i%3)]='O'if q else 'X'
if any([sum(d)==15 for d in c(p[q],3)]):print(f'P{q+1} wins');break
if len(p[q])>4:print(f"Draw");break
q^=1
ungolfed string version
it checks the number of moves the player made before it breaks
but it doesn't catch wrong moves --- so you can place X's over O's
I mean, instead of deleting an item just increment some counter C.
and when C==8, break
while C<8:
import itertools as c
m='2769516438'
p=[[],[]]
q=0
r=print
h="โโผโโผโ"
b=[*map(list,["7โ8โ9",h,"4โ5โ6",h,"1โ2โ3"])]
C=0
while C<8:
r('\n'.join(map(''.join,b)));i=int(input(f"P{q+1} move: "))-1;p[q]+=[int(m[i])];C-=1;b[-1-2*(i//3)][2*(i%3)]='XO'[q]
if any([sum(d)==15for d in c.combinations(p[q],3)]):r(f'P{q+1} wins');C=8
elif C>7:r(f"Draw")
q^=1
Well make it a string or list now
i need the strings as lists so i can change them, yep
without deleting from the dict, the program doesn't detect wrong moves though---i don't like that
C>7 :)
i added a few bytes to redraw the board one last time to see the final position
Maybe create another string z and add 'removed' keys there?
what does ~ do? i think i can use it instead of -1-?
it works, but it doesn't save bytes cause i need to use parenthesis
just same bytes, but it looks more esoteric
import itertools as c;m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0;r=print;h="โโผโโผโ";b=[*map(list,["7โ8โ9",h,"4โ5โ6",h,"1โ2โ3"])]
def f(): r('\n'.join(map(''.join,b)))
f()
while m:
i=int(input(f"P{q+1} move: "))-1;p[q]+=[m[i]];del m[i];b[~(2*(i//3))][i%3<<1]='XO'[q]
if any([sum(d)==15for d in c.combinations(p[q],3)]):r(f'P{q+1} wins');m=0
elif not m:r(f"Draw")
f();q^=1
You can make it catch errors with strings.
create a string z and every time a move is made, add the cell there.
Then, right after you receive i, run the expression 1/(z.find(str(i))<0)
gonna end up using more bytes than the dict
Really?
i dunno, seems like it
wait, if i flip the terms around maybe i can remove parenthesis
that's a negative
hmm, can't i save some bytes by not assigning b the first time
Pretty trivial, but player0/1 instead of 1/2
Saves the+1
And dont think you need a fstring for "draw"
@zealous widget
oh, haha, how long have i had that
Hahaha
Well it saves +1 two times
fair, i've sacrificed a few bytes for some niceties though, but i don't mind going to different player names
Can you post the updated one
"""
Golfing tic-tac-toe with magic squares
m is our magic square it looks like:
4 | 3 | 8
9 | 5 | 1
2 | 7 | 6
Note that all the rows, columns and diagonals sum to 15.
We translate a player's move into a magic square value and then check if any
combinations of 3 moves from a player sum to 15. If any do, they win!
p is the list of the two players moves. (p[0] for player 0's moves, p[1] for
player 1's)
q is which player's turn it is.
b is our board and f() prints the board
"""
import itertools as c;m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0;r=print;h='โโผโโผโ';b=[*map(list,['7โ8โ9',h,'4โ5โ6',h,'1โ2โ3'])]
def f(): r('\n'.join(map(''.join,b)))
f()
while m:
i=int(input(f'P{q} move: '))-1;u=m.pop(i);p[q]+=[u];b[~(2*(i//3))][i%3<<1]='XO'[q];f()
if any([sum(d)==15for d in c.combinations(p[q],3)]):r(f'P{q} wins');m=0
elif not m:r('Draw')
q^=1
my magic square is upside down
Does it matter?
Remove the -1 from the input and move it into m
won't work, ruins the indexing of b
Oh
you can change that if you change the grid values altogether, but i like the board looking like a numpad because otherwise when i'm testing it i keep entering the wrong squares
i'll consider it a 'constraint'
i'll be off soon as well, gn
Cya
any() can take a gen expression so you can just do
any(sum(d)==15for d in c.combinations(p[q],3))```
you can also do from itertools import* then use combinations to save a byte
from itertools import*;m={0:2,1:7,2:6,3:9,4:5,5:1,6:4,7:3,8:8};p=[[],[]];q=0;r=print;h='โโผโโผโ';b=[*map(list,['7โ8โ9',h,'4โ5โ6',h,'1โ2โ3'])]
def f():r('\n'.join(map(''.join,b)))
f()
while m:
i=int(input(f'P{q} move: '))-1;u=m.pop(i);p[q]+=[u];b[~(2*(i//3))][i%3<<1]='XO'[q];f()
if any(sum(d)==15for d in combinations(p[q],3)):r(f'P{q} wins');m=0
elif not m:r('Draw')
q^=1```
i think you can also just use a list instead of a dict right
from itertools import*;m=[2,7,6,9,5,1,4,3,8];p=[[],[]];q=0;r=print;h='โโผโโผโ';b=[*map(list,['7โ8โ9',h,'4โ5โ6',h,'1โ2โ3'])]
def f():r('\n'.join(map(''.join,b)))
f()
while m:
i=int(input(f'P{q} move: '))-1;u=m.pop(i);p[q]+=[u];b[~(2*(i//3))][i%3<<1]='XO'[q];f()
if any(sum(d)==15for d in combinations(p[q],3)):r(f'P{q} wins');m=0
elif not m:r('Draw')
q^=1```
oh actually nvm that messes up the indexing
@sick hound py dict(enumerate([2,7,6,9,5,1,4,3,8])) this is a shorter way to get the dict tho
@grizzled cloak ^
@zealous widget ^
tru
Haha, glad my thing is used
Haha, why stuff is overridable
Like, 1-1 and we have O at 1
map(int,list('276941438')) this is 4 bytes shorter for getting that list
why would you need a list?
You can't pop from a map object
Well, m is shorter than this
[*map(int,'276941438')]
[int(i)for i in'276941438']
nice guys, you saved a couple of bytes
saved a couple bytes in the indexing math with ~(i//3*2)
[*map(int,'276941438')] is longer than [2,7,6,9,5,1,4,3,8] rip
<sarcasm>write a program that golfs python code
wut
using unpacking i saved some bytes:
from itertools import*;m,p,q,r,s,l=dict(enumerate([2,7,6,9,5,1,4,3,8])),[[],[]],0,print,'โโผโโผโ',' โ โ ';b=[*map(list,[l,s,l,s,l])]
def f(): r('\n'.join(map(''.join,b)))
f()
while m:
i=int(input(f'P{q} move: '))-1;u=m.pop(i);p[q]+=[u];b[~(i//3*2)][i%3*2]='XO'[q];f()
if any(sum(d)==15for d in combinations(p[q],3)):r(f'P{q} wins');m=0
elif not m:r('Draw')
q^=1
impressive
ok, here's one from a help channel:
Qfu
:
I need some python help
Make a program that can expand a polynomial.
Example:
Input: (x+y)^3
Output: (x)^3 + 3(x)^2(y)^1 + 3(x)^1(y)^2 + (y)^3
i did this with the standard library using itertools.product and Counter:
from itertools import product
from collections import Counter
def get_input():
term = input("Input in the form of '(x + y + ...)^n': ")
return term
def parse_input(term):
i = 1
while term[-(i+1)].isnumeric():
i+=1
n = int(term[-i:]) #Exponent
term = term[:-i]
term = term.replace("(","").replace(")","")
term = term.replace(" ","").replace("^","").split("+")
return term, n
def expand(term, n):
expanded = list(product(*(term for _ in range(n))))
for i, term in enumerate(expanded):
expanded[i]="".join(f"({key}{f'^{val}' if val > 1 else ''})"
for key,val in Counter(sorted(term)).items())
return " + ".join(f"{val if val > 1 else ''}{key}"
for key,val in Counter(sorted(expanded)).items())
if __name__ == "__main__":
print(expand(*parse_input(get_input())))
now, try to golf it
example outputs:
Input in the form of '(x + y + ...)^n': (x + y)^3
3(x)(y^2) + 3(x^2)(y) + (x^3) + (y^3)
Input in the form of '(x + y + ...)^n': (x + y + z)^2
2(x)(y) + 2(x)(z) + (x^2) + 2(y)(z) + (y^2) + (z^2)
what about golfing connect 4
connect 4 would be fun
connect ~-5
from itertools import*;from collections import*;c=Counter;s=sorted
a=input("Input in the form of '(x + y + ...)^n': ")
t,e=a.split('^');e=[*product(*(t.translate({40:'',41:''}).split('+') for _ in range(int(e))))]
for i,j in enumerate(e):
e[i]="".join(f"({k}{['',f'^{v}'][v>1]})"for k,v in c(s(j)).items())
print(" + ".join(f"{['',v][v>1]}{k}"for k,v in c(s(e)).items()))
Connect 4 is like a slightly bigger noughts and crosses
well, except you can't place noughts anywhere since they fill from the bottom---and the magic square method of checking three-in-a-row doesn't work
that's a nice golf @sick hound
Good point
Though you can do things where (atleast for vertical and horizontal) you can translate the column/row as a single number
you probably don't need to define the functions since we only use them once, poke
And we know hat specific numbers will correspond to settings
oh true
So you could just lookup the letter
But then how do you do diagonald
(I was doing something like this for just physically possible boards a while ago)
can you rename split? probably not because its a method?
Never got round to checking win states
i'd probably check that all combinations of 4 moves satisfy one of 4 linear equations
...
sorry /dev/log, you had a similar name to poke
I do
i pressed enter too fast
Lol
@zealous widget wdym rename split?
similar to how we golf repeated uses of other functions by assigning them to a single letter variable
is what i meant
beat me by one second lmao
:D
gotta get rid of the extra spaces @sick hound
Input in the form of '(x + y + ...)^n': (x + y + z)^2
2( y )( z) + 2( y )(x ) + ( y ^2) + 2( z)(x ) + ( z^2) + (x ^2)
oh right
another translate term maybe
from itertools import*;from collections import*;c=Counter;s=sorted;a=input("Input in the form of '(x + y + ...)^n': ");t,e=a.split('^');e=[*product(*(t.translate({32:'',40:'',41:''}).split('+')for _ in range(int(e))))]
for i,j in enumerate(e):
e[i]="".join(f"({k}{['',f'^{v}'][v>1]})"for k,v in c(s(j)).items())
print(" + ".join(f"{['',v][v>1]}{k}"for k,v in c(s(e)).items()))
nice
Input in the form of '(x + y + ...)^n': (x + y + w)^4
12(w)(x)(y^2) + 12(w)(x^2)(y) + 4(w)(x^3) + 4(w)(y^3) + 12(w^2)(x)(y) + 6(w^2)(x^2) + 6(w^2)(y^2) + 4(w^3)(x) + 4(w^3)(y) + (w^4) + 4(x)(y^3) + 6(x^2)(y^2) + 4(x^3)(y) + (x^4) + (y^4)
we can make our own symbolic computation module now
there may be a faster way to iteratively or recursively spit out the terms of the polynomials
the product and counter method is admittedly pretty naive
you can save an assignment, by just splitting the input on the spot
and save some bytes by assignment through unpacking
from itertools import*;from collections import*;c=Counter;s=sorted;p=str.split;i=dict.items
a=input("Input in the form of '(x+ y+...)^n': ")
t,e=p(a,'^');e=[*product(*(p(t.translate({32:'',40:'',41:''}),'+')for _ in range(int(e))))]
for i,j in enumerate(e):
e[i]="".join(f"({k}{['',f'^{v}'][v>1]})"for k,v in i(c(s(j))))
print(" + ".join(f"{['',v][v>1]}{k}"for k,v in i(c(s(e)))))``` @sick hound
its a bit shorter i think
yeah that's not a function
from itertools import*;from collections import*;c,s,t,e=Counter,sorted,*input("Input in the form of '(x + y + ...)^n': ").split('^')
e=[*product(*(t.translate({32:'',40:'',41:''}).split('+')for _ in range(int(e))))]
for i,j in enumerate(e):
e[i]="".join(f"({k}{['',f'^{v}'][v>1]})"for k,v in c(s(j)).items())
print(" + ".join(f"{['',v][v>1]}{k}"for k,v in c(s(e)).items()))
from itertools import*;from collections import*;c=Counter;s=sorted;p=str.split;q=dict.items
a=input("Input in the form of '(x+y+...)^n': ")
t,e=p(a,'^');e=[*product(*(p(t.translate({32:'',40:'',41:''}),'+')for _ in range(int(e))))]
for i,j in enumerate(e):
e[i]="".join(f"({k}{['',f'^{v}'][v>1]})"for k,v in q(c(s(j))))
print(" + ".join(f"{['',v][v>1]}{k}"for k,v in q(c(s(e)))))```
try assigning everything all at once with unpacking
ah smart
i think the only way to make it shorter substantially is to research the math into it and reimplement it entirely lol
true probably
yeah, i think i could drum up another iterative method if i sat down with it for a little bit
things to notice: the exponents on each term always sum to n, and the coefficients always match unordered exponent partitions
so there's a lot of repeated calculation
might be better to work with partitions in fact
def partition(collection):
if len(collection) == 1:
return [[collection]]
first = collection[0]
subparts = []
for smaller in partition2(collection[1:]):
# insert `first` in each of the subpartition's subsets
for n, subset in enumerate(smaller):
subparts.append(smaller[:n] + [[first] + subset] + smaller[n+1:])
# put `first` in its own subset
subparts.append([[first]] + smaller)
return subparts
gives:
>>> partition([1,1,1])
[[[1, 1, 1]], [[1], [1, 1]], [[1, 1], [1]], [[1], [1, 1]], [[1], [1], [1]]]
though you could input coefficients with this method
found the wiki article on it https://en.wikipedia.org/wiki/Multinomial_theorem, looks like the summation does depend on partitions of the exponent
though i can't think of a way to save code with any of it
ill take a look once this fight is over
you betting on chun li or ryu?
well, computing the coefficients is real easy given the exponents with the multinomial theorem, but generating the partitions of the exponents is the tough bit....i don't think partitions are in the standard library hence the above function
found this golfed partition function on the stack:
def f(n,i=1,l=[]):n or print(l);i>n or[f(n-i,i,[i]+l),f(n,i+1,l)]
>>> f(1)
[1]
>>> f(2)
[1, 1]
[2]
>>> f(3)
[1, 1, 1]
[2, 1]
[3]
>>> f(4)
[1, 1, 1, 1]
[2, 1, 1]
[3, 1]
[2, 2]
[4]
Whenever you encounter a bug, you can just pop off to the stack, as opposed to popping off the stack.
you'd still need to pad the lists with 0's and then use permutations to generate terms
seems like more work than it's worth
>>> partitions=[[1,1,1],[2,1,0],[3,0,0]]
>>> from itertools import permutations
>>> for partition in partitions:
...: for permutation in permutations(partition):
...: print(f'x^{permutation[0]}y^{permutation[1]}z^{permutation[2]}')
x^1y^1z^1
x^1y^1z^1
x^1y^1z^1
x^1y^1z^1
x^1y^1z^1
x^1y^1z^1
x^2y^1z^0
x^2y^0z^1
x^1y^2z^0
x^1y^0z^2
x^0y^2z^1
x^0y^1z^2
x^3y^0z^0
x^3y^0z^0
x^0y^3z^0
x^0y^0z^3
x^0y^3z^0
x^0y^0z^3
from textwrap import*;exec("def f(n,b,s=''):\n while(n>0):n,x=divmod(n,b);s+=r(x)\n return s[::-1]");r=lambda n:chr(n+48 if 0<=n<=9 else n+87);c=lambda s:'{:x}'.format(int("n".join('{:x}'.format(int("".join('{:x}'.format(ord(n)+64)for n in str(ord(c)))))for c in s),36));d=lambda d:"".join(chr(int("".join(chr(int(x,16)-64)for x in wrap(str(int(p,16)),2))))for p in f(int(d,16),36).split("n"))
Is there a way to make this code shorter? (without f-strings)
@marsh void showing un-obfuscated code first could help ๐
since you use '{:x}'.format so much you could put it in a variable py from textwrap import*;exec("def f(n,b,s=''):\n while(n>0):n,x=divmod(n,b);s+=r(x)\n return s[::-1]");a='{:x}'.format;r=lambda n:chr(n+48 if 0<=n<=9 else n+87);c=lambda s:a(int("n".join(a(int("".join(a(ord(n)+64)for n in str(ord(c)))))for c in s),36));d=lambda d:"".join(chr(int("".join(chr(int(x,16)-64)for x in wrap(str(int(p,16)),2))))for p in f(int(d,16),36).split("n"))
you can do the same with int py from textwrap import*;exec("def f(n,b,s=''):\n while(n>0):n,x=divmod(n,b);s+=r(x)\n return s[::-1]");a='{:x}'.format;b=int;r=lambda n:chr(n+48 if 0<=n<=9 else n+87);c=lambda s:a(b("n".join(a(int("".join(a(ord(n)+64)for n in str(ord(c)))))for c in s),36));d=lambda d:"".join(chr(b("".join(chr(b(x,16)-64)for x in wrap(str(b(p,16)),2))))for p in f(b(d,16),36).split("n"))
you can also shorten r by two characters py from textwrap import*;exec("def f(n,b,s=''):\n while(n>0):n,x=divmod(n,b);s+=r(x)\n return s[::-1]");a='{:x}'.format;b=int;r=lambda n:chr(n+48if 0<=n<=9else n+87);c=lambda s:a(b("n".join(a(int("".join(a(ord(n)+64)for n in str(ord(c)))))for c in s),36));d=lambda d:"".join(chr(b("".join(chr(b(x,16)-64)for x in wrap(str(b(p,16)),2))))for p in f(b(d,16),36).split("n"))
and also put "".join in a variable py from textwrap import*;exec("def f(n,b,s=''):\n while(n>0):n,x=divmod(n,b);s+=r(x)\n return s[::-1]");a='{:x}'.format;b=int;e=''.join;r=lambda n:chr(n+48if 0<=n<=9else n+87);c=lambda s:a(b("n".join(a(int(e(a(ord(n)+64)for n in str(ord(c)))))for c in s),36));d=lambda d:e(chr(b(e(chr(b(x,16)-64)for x in wrap(str(b(p,16)),2))))for p in f(b(d,16),36).split("n"))
@marsh void obfuscated and unreadable, we have no idea what it is
That was the goal actually
Well, it uses chr(), base 36, hexadecimal conversion mostly
And returns hash-looking hexadecimal string
@sick hound ```py
c('NeKitDS') -> '60be4dcf30143febf568739ba6239c17f57b58edefb9dd1'
Is it reversible?
Nice
>>> x = c('NeKitDS')
>>> x
'60be4dcf30143febf568739ba6239c17f57b58edefb9dd1'
>>> y = c('NeKit')
>>> y
'772ac0667661001701bca4b28e49c829d4'
>>> d(x)
'NeKitDS'
>>> d(y)
'NeKit'
The help channels are occupied, and this is really strange behavior, so I think I'll write it here.
https://pastebin.com/5ZNvCVLq
If I do exec(code) and define a function inside an exec:
def fib(n):
if n <= 2:
return 1
else:
return fib(n-1) + fib(n-2)
fib(6)
It will tell me that at line return fib(n-1) + fib(n-2) fib is not defined!
Unless I but global fib after the def line.
But if I do this:
def run_stuff():
pass
code_object = compile(code, "<string>", "exec")
run_stuff.__code__ = code_object
run_stuff()
It works as expected without global!
Why?
can't repro
>>> exec("""
... def fib(n):
... if n <= 2: return 1
... return fib(n - 1) + fib(n - 2)
... """.strip())
>>> fib(2)
1
>>> fib(3)
2
>>> fib(4)
3
>>> fib(5)
5
>>>
I think it's due to the way your other code works
aka the problem isn't what you asked
Hi guys,
Is searching for undefined variables using AST an isoteric task?
i.e. py src = '''a; b = 1 '''
here b is defined, a is undefined. I need to find all such undefined variables (that cause NameError) using AST
Mp is really weird when it comes to scopes and sharing data across instances
esoteric kinda
but not really in the common sense
more like "why would i ever need to do that programmatically"
Well let's say you need to check the file for a NameError (Not defined). however, the code should not run. I thought it could be implemented with ast
i think it'd be fairly simple
I am advised to use pyflakes.
I think this is a bit redundant for my needs.
I want to check for NameError only the code of my modules. I do not use there any hacks with globals(), etc.
that is, the solution should be simple, imo.
for example in this code I just need to get message that the variables a and D are undefined.
a
b = 1
class C(D): pass
@sick hound id regex match for a equals someval
If you cant find that its not defined
Or search for "def a..."
Etc
@grizzled cloak that wont catch scoping. but tbh i dont see why anyone would want to do this
It would catch scoping if you check indents
But idk thats just rewriting python
Just try catch nameerror
from textwrap import*;exec("def f(n,b,s=''):\n while(n>0):n,x=divmod(n,b);s+=r(x)\n return s[::-1]");a='{:x}'.format;b=int;e=''.join;r=lambda n:chr(n+48 if 0<=n<=9 else n+87);c=lambda s:(a(b("n".join(a(int(e(a(ord(n)+64)for n in str(ord(c)))))for c in s),36))if s else s);d=lambda d:(e(chr(b(e(chr(b(x,16)-64)for x in wrap(str(b(p,16)),2))))for p in f(b(d,16),36).split("n"))if d else d)
Made this thing return input if it is empty
Why are you execing a lot of code?
Just so that its on one line?
Meh I feel like saving the 8 chars and having it on +1 line is better
def f(n,b,s=''):
while(n>0):n,x=divmod(n,b);s+=r(x)
return s[::-1]
Idk how to oneline
Haha thanks
Me: writing clean code
Also me: #esoteric-python
@rugged sparrow this is r() if you need it r=lambda n:chr(n+48 if 0<=n<=9 else n+87)
๐
Oh man imagine a ide that automatically "esoteric-fies" your code
As you are typing
If you want it or not
Only one letter vars
No spaces
A lot of oneliners
@rugged sparrow I just want to import certain modules implicitly (automatically).
that is, by importing the code above, I would like to find variables that correspond to the names of the modules and import them first to avoid NameError.
i.e. actually importing code
a
b = 1
class C(D): pass
I could import the code
from q import a
from d import D
a
b = 1
class C(D): pass
this would allow me not to write imports of some modules every time.
But what if you have two modules that both have a?
Ie time.time and datetime.time
Also, pycharm can do this so you might want to look into how they do it
I just will make sure that this does not happen (two modules that both have a)
@marsh void whats some example input/output for f
f?
Ok lemme see
f takes integers n and b
n is decimal number and b is a base it needs to be converted to
>>> f(36,36)
'10'
And it returns string representation of n in base b
@rugged sparrow here ^
ok
f = lambda n,b,s=[]:[
[*iter(
lambda g={'n':n,'b':b}:[
(
lambda m=divmod(g['n'],g['b']):g.update({'n':m[0],'x':m[1]})
)(),
s.append(r(g['x'])),
g['n']>0
][2],
0)
],
''.join(s)[::-1],
s.clear()
][1]``` @marsh void just remove all newlines and tabs
Oh yes
and im happy to explain any part of it
Well, it slow as fuck if youโll excuse my French
hmm?
Like, it is doing iter, append... well yeah it should be somewhat the same speed lol
Haha, I am actually understanding almost everything in it
so iter can take 2 args
iter(func,flag)
and it will stop calling func when func returns flag
so i use func to append to s=[] and then at the end just join it as a string
[*iter(int,1)]
Lol
yea while True is optimized
Maybe there is 2-char builtin func name
maybe
Nah, I think there isnโt actually
id, but it needs an arg
I love how one-lining people use tuples and indexes to add several instructions
it helps to keep things shorter
Yeah actually
When do integers break in python?
I wanna test limits of my cipher thingy
max int is somewhere in sys
The actual question is though, when does hex() break I think
i dont think it does till you hit max int size
@rugged sparrow sys.int_info(bits_per_digit=30, sizeof_digit=4)
ah
So is it a sequence of digits actually, an integer

60be4dcf30143febf568739ba6239c17f57b58edefb9dd1 can someone try to decode this to an original string, as if you havenโt seen my code
doubt anyone would figure that out
yea
@marsh void what is the code?
The code?
to decode it
d=lambda d:(e(chr(b(e(chr(b(x,16)-64)for x in wrap(str(b(p,16)),2))))for p in f(b(d,16),36).split("n"))if d else d)
f can be found above
@marsh void is r only used in f?
and is f only used in d
hahaha
im gonna do it
hm?
encoder = lambda i,encode,a='{:x}'.format,b=int,e=''.join,w=__import__('textwrap').wrap:(lambda s:(a(b("n".join(a(b(e(a(ord(n)+64)for n in str(ord(c)))))for c in s),36))if s else s))(i) if encode else (lambda d:(e(chr(b(e(chr(b(x,16)-64)for x in w(str(b(p,16)),2))))for p in (lambda n,b,s=[]:[[*iter(lambda g={'n':n,'b':b}:[(lambda m=divmod(g['n'],g['b']):g.update({'n':m[0],'x':m[1]}))(),s.append((lambda n:chr(n+48 if 0<=n<=9 else n+87))(g['x'])),g['n']>0][2],0)],e(s)[::-1],s.clear()][1])(b(d,16),36).split("n"))if d else d))(i)``` @marsh void its now a single function
Holy fuck
This is even more unreadable than it was
@rugged sparrow donโt mind comparing speed of yours and mine though? I am doing homework rn
encoder('chilaxan',encode=True) => '704a86d5413498c9ee971fb169d04a8a10ee279ee2add58a8a46c9ce'
encoder('704a86d5413498c9ee971fb169d04a8a10ee279ee2add58a8a46c9ce',encode=False) => 'chilaxan'```
should be exactly the same
i just wrapped it in one more lambda and used __import__
and moved some stuff out of variables
Is import caching imported modules?
yes
I mean __import__
oh no
it just returns the module object
globals().update({'textwrap':__import__('textwrap')}) is (pretty much at least) import textwrap
Well yeah
Oh yeah, it makes sense you initialized it too
The best thing is, you made it unreadable, having all locals inside and without globalising anything except the function
haha
most of my oneline stuff is unreadable
especially the niche stuff. like try/except style stuff
and with x() as y
is there a way to await something in a lambda and get its return
You mean https://github.com/mental32/lambda_bot/blob/master/lambda_bot.py probably
A discord bot written with pure lambdas using discord.py - mental32/lambda_bot
If I'm not mistaken, it adds the coroutines as a task to the loop, but doesn't await the result of the tasks (since that's not needed to run the bot itself)
So, the __await attribute mental32 writes on the bot is just a create_task lambda
.result() tbh
that will raise an exception if the task has not yet finished, though
It also should raise exception if fut.exception() is not None iirc
remember i only have one line to use
You can do try exceptd on one line
duno how well that will work in a lambda
how?
I'm not at home rn but I'll send around 9ish
Like an hr from now but tbh I just got home @wild cairn
@wild cairn there's the file ^
Oh whoops I thought you wanted try except. Well with asyncio how would you normally wait for a function to finish?
Just in general, I have done next to nothing with async
two not so esoteric but still fun ways to map some letters to random numbers.
assign_random_number = lambda letters: [(l,i) for i,l in enumerate(sorted(letters, key=lambda: random.random()))]```
but of course numpy has a inline function equivalent of shuffle:
```py
arn = lambda letters: [(l, i) for i, l in enumerate(np.random.permutation(letters))]```
someone had asked for help on how to do this yesterday in one of the help channels
the problem was that random.shuffle does not return a shuffled copy of the array but actually shuffles the array so you would have to copy it yourself and then shuffle it
coincidentally i had just done something with sorting items with the key argument so i just had to use it haha
I think you can also do random.sample(letters, len(letters)) to randomly shuffle a list
(lambda c,s,n=lambda s,n:len(s)+n if n<0 else n:c(id(tuple.__dict__)+16).value.update({'setitem':lambda self,index,val:(self[n(self,index)],[*map(setattr,[s(val),s(self[n(self,index)])],['refcnt']*2,[s(val).refcnt+1,s(self[n(self,index)]).refcnt-1])],setattr(c(id(self)+24+(8*n(self,index))),'value',val))[2]}))(*(lambda c=__import__('ctypes'):(c.py_object.from_address,lambda o:type('',(c.Structure,),{'_fields_':[('refcnt',c.c_long)]}).from_address(id(o))))())
``` new tuple.setitem (uses refcounting properly now (at least i think))
so it can just be dict(zip(random.sample(letters, len(letters)), range(len(letters)))
Sorry for lack of codeblocks Iโm on mobile
Or if you want (number, letter) you can just do dict(enumerate(random.sample(letters, len(letters))))
((...), 2, 3)
i dont get it.
isnt ... the same as pass?
oh is it because it leaves the parentheses?
no, other stuff does that too
it represents reference to an object in itself
Well
x = []
x.append(x)
print(x)
my code lets you do that with tuples
Yep 
it also supports negative indexing now
((Ellipsis), 1,1)
Out[31]: (Ellipsis, 1, 1)```
im currently trying to figure out how to make py (0,1,2)[0] = 1 work
Lol
Well, you need to write __setitem__ but with some tricky way
Writing to a __dict__ wont work
yea i need to add it to the PyTuple_Type struct
Yeah but how 
lol
im in lit rn lmao
but I am still honest
I mean, homework to learn a poem that is 52 lines long for one day (literally have that tomorrow) is kind of not what you would expect
fair
i just found out something cool
you can mutate map the map arg list inside the map func
(lambda x=[0]:[*map(lambda y:x.append(y+1),x)])()```
wonder what i can use that for
ooooooooo recursion
easy recursion (well maybe not)
Class body functions begin with assigning __module__ from LOAD_NAME 0 (__name__), does anyone know why having a variable called name in an enclosing scope doesn't override it?
e.g. ```py
class A:
name='foo'
class B: pass
A.B.module # 'main'
def f():
name='foo'
class B: pass
return B
f().module # 'main'```
does LOAD_NAME only look at direct locals and globals, and not lexical scopes?
you called F instead of f
that was a typo
woo, got it to 'work' by creating a slot variable
>>> def f():
... __name__='foo'
... class B:
... nonlocal __name__
... return B
...
>>> f().__module__
'foo'```
nice
didn't think of that because normal functions d..
wait then
how does
>>> def foo():
... a = 1
... class B:
... b = a + 1
... return B
...
>>> foo().b
2```
oh, a uses LOAD_CLASSDEREF instead of LOAD_NAME
so the name load is a special case because name is expected to be global, whereas normally free variables in class bodies are loaded with LOAD_CLASSDEREF
i guess that makes sense
but why isn't it LOAD_GLOBAL then
since it's apparently directly inserted rather than codegenned as a normal access
wait, it is codegenned
str = PyUnicode_InternFromString("__name__");
if (!str || !compiler_nameop(c, str, Load)) {```
so why doesn't it become LOAD_CLASSDEREF in the presence of an enclosing-scope variable
or global (as if there were a global __name__ statement)
@brisk zenith hows the cpystructs module coming along?
progress is sorta on and off, but i've had some really good ideas and stuff for how to implement it
Nice
it will probably make replacing dunder methods easier and thus my goal of making tuples traditionally mutable easier lmao
Python bytecode is pretty cool, learning about it now
End goal is to make a code generator for rust that converts tokens into bytecode
So I can potentially make my own programming language translate into optimised python bytecode using a memory-safe "compiler" (really code generator + anything anyone implaments) :)
I don't understand. Is Rust the name of your own language, or do you mean the pre-existing compiled language?
nom --> custom code generator --> cpython/etc
First 2 are made in the Rust language (https://www.rust-lang.org/)
@snow beacon
So it's a rust program that compiles nom code to Python bytecode?
Rust program that compiles the output of a custom parser (that I used nom for behind-the-scenes to speed up development) to python bytecode
Problem is that I have no idea how it all works
i just wrote this code for someone, i feel like i'm summoning evil spirits
import os
from glob import glob
utility_blacklist = {'dont_load_me.py'}
for filename in glob('plugins/utility/*.py'):
modname = os.path.basename(filename).replace('.py', '')
if modname.startswith('_') or modname in utility_blacklist:
continue
print 'Auto-loading module: %s' % modname
exec('from utility import %s' % modname)
python 2.7 no less
@sonic ginkgo cool)
In which line does importlib work?
import os
from glob import glob
from importlib import import_module
utility_blacklist = {'dont_load_me.py'}
for filename in glob('plugins/utility/*.py'):
modname = os.path.basename(filename).replace('.py', '')
if modname.startswith('_') or modname in utility_blacklist:
continue
print 'Auto-loading module: %s' % modname
globals()[modname] = import_module('utility.%s' % modname)
don't think that's any better but ๐คท
I plan to implement something like implicit import of modules for some of my projects.
that is when importing module x, the following will happen:
- Using ast, program finds the classes that are called in this module.
- if the module has a name from the dictionary
{module_name: import_from_here}, then program imports this module - after all such imports, the program just imports the module
xin any way.
This may allow me not to write manually each time from where to import certain modules, because the program can do this automatically.
so you are not alone in calling evil spirits:)
Also today I was trying to somehow turn the decorator into with statement.
before:
@decorate
def x ():
ย ย ย ย ...
after:
with decorate:
ย ย ย ย ...
This could be useful, because in some cases I do not need to create a separate function (in this case x) manually.
that is, I would just like to be able to decorate certain lines of code, not just functions.
so idea is first to get module and linenumber from where Test class called.
something like this
import inspect
class Test():
def __init__(self):
curframe = inspect.currentframe()
calframe = inspect.getouterframes(curframe, 2)
print(calframe[1][2])
def __enter__(self):
pass
def __exit__(self, type, value, traceback):
pass
with Test():
print (1)
with Test():
print (2)
Then I could use AST to get with statement source.
And I stopped here because I don't know what's to do next.
I guess I needto create function from 'with' body, then add appropriate decorator, and then exec it?
yep
oh yeah i guess i could have used ast to construct an import statement
there's more than one way to break python
@sick hound look at https://docs.python.org/3/library/contextlib.html
@rugged sparrow this does not solve my problem unfortunately.
I have maybe a little crazy idea: in certain cases, I want to use with as if I were using a decorator. that is, I want to write
with decorate ():
something``` which would actually mean ```py
@decorate
def x():
something```
my goal is try to get rid of the need to create a separate method for each decorator (sometimes it can be illogical and inconvenient).
in other words, I would like to be able to decorate individual lines of code (without the need to manually create a function for this)
Look at ContextDecorator
ok ty let me check it
@rugged sparrow well this is something like with in the form of a decorator, and I need the opposite thing.
my first idea was this:
...
@decorate
print (2) # decorate this line
...
that is, initially my desire was that I wanted the above example to work.
this would mean decorating the expression print (2) โ only one line.
In the current version of python, I canโt do this because I need to create a separate function in order to use decorator.
but then I thought that it would be inconvenient, because if I need to decorate several lines, then I need to write @decorate for each line
then I thought that it would be good to use with
i.e. to use with, which would work as a decorator.
@sick hound what exactly are you trying to do?
- I want to decorate a line of code, right in the code.
- it would be convenient to decorate several consecutive lines
and thats all for now:)
@rugged sparrow here is an example
def decorate(foo):
def inner():
print ('hello')
foo()
return inner
@decorate
def x():
print ('world')
this is how decorators works
and I want them to work like this
def decorate(foo):
def inner():
print ('hello')
foo()
return inner
@decorate
print ('world')
That's always gonna throw a syntax error
yea I know
@rugged sparrow
and since I don't want to break python syntax, my idea is to use with
something like
with decorate():
print ('world')
print ('!')
So write it as a with statement
@rugged sparrow
I want to use this as a full-fledged decorator
I mean for example something like this
def decorate(foo):
def inner():
foo()
foo()
return inner
@decorate
def x():
print ('world')
print ('!')
x()
so I have an idea to turn the body of with statement into a function, then add a decorator and exec it.
Do you want to convert a pre-existing decorator into a context manager without rewriting the decorator?
@snow beacon well yea, there is some decorator
and I want to use 'with' statement thich means body of this statement turns into a function and this function is decorated.
this is Y problem maybe, and if so, then the X problem is to be able to decorate just one or several lines of a code right there
(these lines are automatically transformed into some temp function then this function is decorated)
I'm fairly certain this is impossible with just a context manager, unless you did something fancy with settrace or edited Python itself. If you don't want to use a decorator because it's an extra line compared to with, you could call a function on a string containing your lines of code that execs them. e.g. python decorate_exec("print('world')\n" "print('!')")
I think the easiest way is a decorator python @decorate def _(): print("world") print("!")
The problem with with is that it doesn't seem to compile the body of it into an object you can run multiple times. You can skip it, but you can't run it like you would a function. For that, you need a code object.
Well yes it seems I will use settrace for ignoring executing of with body (didn't find a better way).
So the main idea is just
-
get module name and lineno from where the Test class called (I will call it only from with statement)
[with Test(): ...] -
get end line of this
withstatement -
so knowing start and end of code I get the whole
withstatement code source (string) -
create decorated temp function from the code that I got in (3)
That is
4.1) change first line todef my_temp_foo():
4.2) add decorated line. -
just exec this function
@snow beacon The problem with default decorators is not only that they add an additional line, but that I need to create an additional function for this myself and thus break the structure of the code. imagine you have a code
a
b
c
d
f
e``` and you want to decorate the lines a, c-d, e. using the usual decorator you need to create three separate functions for this, regardless of whether the creation is necessary for you. I just want to make it more transparent and more convenient (albeit slower) with `with` statement
challenge 10 has entered the arena: code/string obfuscation!
hey what's up? bet you weren't expecting one of these. sorry for my inactivity with these over the past couple months (and in pydis in general recently). hopefully i'll be able to keep on top of it from now on. thanks to @gilded orchid for giving me a similar idea to this a while ago!
the challenge here is to create a program which obfuscates strings or code while keeping functionality in tact. more information and an example can be found on the repo: https://github.com/python-discord/esoteric-python-challenges/tree/master/challenges/10-code-obfuscator
i'm relatively busy for the rest of today so if any submissions are created today, they will probably be reviewed tomorrow. i'm looking forward to seeing some fancy ideas though, as always :D
this is gona be fun failing at xD
oh wow, I completely forgot about that suggestion, might give this a shot later
haha yeah it was almost 3 months ago.
remember, if anybody wants to make submissions for earlier challenges while waiting for new ones to come out, i'll be more than happy to review and merge them and stuff :D
this is going well, it's making "o" to chr(int(chr(int('110110', 2))+chr(int('1100110', 2)),16))
How obfuscated are we talking?
Not obfuscated enough
gona do more, this is just a start.
make it so it can do bases other than 2 randomly
@grizzled cloak about as obfuscated as you'd like. the more the better, though!
Enter string to obfuscate: hello
>>> len(obfuscated_string)
3504
spits out a list of this many 2-tuples
Haha, I see salt is very into image stuff
well, i had an idea to take the resulting graph and run it through a reversible SDCA and then use the edge-list from that as the obfuscated string, but probably it wouldn't look visually any more obfuscated
list -- > dict of dicts looks more obfuscated
Yep
everyone should just use Hy
the ultimate esoteric python exercise, except it's actually useful
@sonic ginkgo but writing terrible lambdas is so much more fun
we should move to using actual lisp for better terrible lambdas
Lol
wondering if I should submit my 4 line obfuscator that'sโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ not really esoteric and pretty much only visual
The obfuscator readme is a bit ambiguous. Does our code need to produce python code? Or can it just 'encrypt' a string?
@snow beacon "obfuscate strings or code in a unique way while still keeping functionality fully in tact." I think it needs to be python code, not 100% sure
the obfuscating string challenge reminded me of a code I read a while ago. Googled a bit and found it: https://benkurtovic.com/2014/06/01/obfuscating-hello-world.html
Fun with functional programming in Python | Ben Kurtovic's blog
don't think it's esoteric enough or in the spirit of the challenge to do a submission but was fun to make and play with https://gist.github.com/Numerlor/454b7a1b258e5b984b4b5a433cff940b
@wild cairn by changing the base class with ctypes
how?
from ctypes import py_object
class a:pass
py_object.from_address(id(a)+8).value = type(None)```
how can i do multiple subclasses with that?
seems to work
ยฏ_(ใ)_/ยฏ