#esoteric-python

1 messages ยท Page 73 of 1

distant wave
#
if y := cache_fetch(key) == None:
    y = 
old flint
#

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

distant wave
#

This could be useful:

old flint
#

oof messing with frames

#

I will say I almost considered using execs

distant wave
old flint
#

is there anything that allows me to do

with obj:
    pass

i.e. without a function call?

distant wave
#

Yes, provided you initialize the context manager beforehand

old flint
#

oh I can just make an object with __enter__ and __exit__

#

I guess that's what the contextlib builds

distant wave
#

!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')

night quarryBOT
#

@distant wave Your eval job has completed.

Out of the with block
distant wave
#

Uses the same set_trace hack

old flint
#

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

distant wave
#

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())

night quarryBOT
#

@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
distant wave
#

bleh

old flint
#

lol I was just looking into overriding assignments

distant wave
#

Not sure exactly what I did wrong

#

that's supposed to be a descriptor

#

Ah

#

it doesn't work in the global namespace

old flint
#

lol yea

#

I'd have to do like a y.val sort of thing

#

sigh

distant wave
#

Usually it's best to just put the acquisition code in a function, and wrap it in a caching decorator

old flint
#

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

distant wave
#

Ah

old flint
#

I could write it in an inline function, but I hate those : (

formal sandal
#

You can use a class as a decorator expreesion.

#

Like @class

#

Or any expression whose result is callable.

sick hound
#

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```
snow beacon
#

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.

formal sandal
#

technically you can also use an expression whose result is not callable
I meant that a thing right after @ should be callable.

celest moat
#

!e

night quarryBOT
#
Nah.

Sorry, but you may only use this command within #bot-commands.

rugged sparrow
#

@brisk zenith i used your list __getitem__ replacement code to implement BF using list slicing. would that be a valid submission for challenge 3?

brisk zenith
#

ooh how does it look?

rugged sparrow
#

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

brisk zenith
#

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

rugged sparrow
#

aight

#

im gonna move all the logic into list.__getitem__ and then ill test and submit

stray needleBOT
#

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 "]"

rugged sparrow
#

@brisk zenith it breaks help() somehow

brisk zenith
#

yeah messing with builtins with ctypes can do all sorts of unexpected things

rugged sparrow
#

ยฏ_(ใƒ„)_/ยฏ

#

it works lol

#

at least mostly

rugged sparrow
#

@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

brisk zenith
#

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

rugged sparrow
#

yea

#

thanks

brisk zenith
#

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

rugged sparrow
#

thats where to look? awesome

rugged sparrow
#

@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

calm rampart
#

@rugged sparrow probably

brisk zenith
#

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

marsh void
#

mutable tuple is called a list

brisk zenith
#

not necessarily

marsh void
#

yeah ๐Ÿ˜…

brisk zenith
#

a list can have its size changed, a tuple cannot so easily without causing some pretty funky problems

marsh void
#

I mean yeah that was me not understanding stuff in the past

brisk zenith
#

oh i see :D

marsh void
#

(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

fallen heath
#

a.extend([4, 5])

marsh void
#

Yeah but

rugged sparrow
#

@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
edgy kelp
#

wonder when a seg fault is the expected and wanted behaviour ๐Ÿ˜„

rugged sparrow
#

rarely lmao

#
>>> a = 1
>>> list_dict['append'] = a
>>> list_dict['append']
1
>>> list_dict['append']
1
>>> [].append
<set_iterator object at 0x785608fd9288>``` huh
sick hound
#

what's in this mysterious set iterator object? can you get values from it without a segfault?

marsh void
#

Yeah, new_method is a thing chilaxan had posted before, but wraps a function

rugged sparrow
#

@sick hound I'll test in like 5

marsh void
#

Oh yeah, segfault in mine too xd

rugged sparrow
#
>>> 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
sick hound
#

huh ok

#

wait hang on

#

you did list_dict['append'] = 1

rugged sparrow
#

yea

#

list.append became 1

#

list().append gets weird

sick hound
#

last time you did a = 1; list_dict['append'] = a

#

not sure if that makes a difference though

rugged sparrow
#
>>> 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

sick hound
#

oh

rugged sparrow
#
>>> 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

rugged sparrow
#
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)

sick hound
#

built-in function write?

#

where is it getting that from

rugged sparrow
#

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 ^

edgy kelp
#

only if we could

while True:
    try:
        list.append(1, 2, 3)
    except SegmentationFault:
        pass

๐Ÿ˜„

wind maple
#

๐Ÿค”

rugged sparrow
#

@sick hound I figured it out I believe. I think the lambda was being deallocated

rugged sparrow
#

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)
marsh void
#

Haha I have actually started this all ๐Ÿ˜…

marsh void
#

Let's just do it with appendmany?

grizzled cloak
#

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?

rugged sparrow
#

@grizzled cloak what does that do?

grizzled cloak
#

converts a discord servers id into when it was created

rugged sparrow
#

oh thats cool

grizzled cloak
rugged sparrow
#

thats super cool actually

#

nice

grizzled cloak
#

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))```
night quarryBOT
#
No way, Josรฉ.

Sorry, but you may only use this command within #bot-commands.

grizzled cloak
#

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))```
edgy kelp
#

that zfill is out of place ๐Ÿ˜›

#
f"{f'{d:b}':0>64}"
grizzled cloak
#

Fstring-ception

edgy kelp
#

if I could jsut drop the > it'd also be shorter ๐Ÿ˜„

zealous widget
#

you should be able to just nest brackets

rugged sparrow
#
>>> f'{{10:b}:0>64}'
  File "<stdin>", line 1
SyntaxError: f-string: single '}' is not allowed``` @zealous widget
zealous widget
#

i've nested brackets before hmm:

f'{"hi":>{30 - 20}}'
 '        hi'
rugged sparrow
#

hmm

edgy kelp
#

guess it depends on the side

rugged sparrow
#

yea

edgy kelp
#

when I put it on the left it wants to assign a variable to b

grizzled cloak
#

what are some fun esoteric challenges?

#

maybe something that focuses on efficiency

rugged sparrow
#

@grizzled cloak golf tictactoe

marsh void
#

Haha, this one is mhh

#

Idk why did I post it here though, I since it isn't real golfing

grizzled cloak
#

isnt golfing writing it in as few chars as possible?

rugged sparrow
#

Yeah

grizzled cloak
#

nk

#

mk

#

what is a good amount of chars for tictactoe?

zealous widget
#

depends, is it for two players or does the computer play one side

grizzled cloak
#

2 players

#

no minimax for me

rugged sparrow
#

Just try to golf it

zealous widget
#

i'd just pick random moves for a computer player

rugged sparrow
#

See how low you can go

zealous widget
#
How about a nice game of chess?
grizzled cloak
#

isnt that from wargames?

zealous widget
#

yep

grizzled cloak
#

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

edgy kelp
#

that'd be a lot easier for the rotating

grizzled cloak
#

yeah

#

when golfing you are allowed to use numpy right?

zealous widget
#

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

grizzled cloak
#

wow

#

no way you just know that

zealous widget
#

what do you mean? that was an original thought by me

edgy kelp
#

magic squares are pretty common but never would've though about them for tictactoe ๐Ÿ˜„

grizzled cloak
#

first time ive heard of them

zealous widget
#

i wouldn't use numpy, but i might use itertools.combinations

grizzled cloak
#
type(np.NaN)
Out[85]: float```
hmmm
zealous widget
#

unless you wanted to use numpy just for pretty printing the array

edgy kelp
#

apart from getting to know the suqares in school I bumped into a few challenges for python regarding htem

zealous widget
#

generating magic squares would be a challenge in itself

grizzled cloak
#

so how many chars would you say would a solution using magic squares use?

zealous widget
#

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

grizzled cloak
#

hmm

#

can i somehow make all see -1 as False?

edgy kelp
#

Must it be -1?

grizzled cloak
#

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

zealous widget
#

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

grizzled cloak
#

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

zealous widget
#

array[::-1].T

grizzled cloak
#

hm?

zealous widget
#

that's how you turn it 90 degrees

grizzled cloak
#

np.rot90(board)

#

but that is shorter so why not!

zealous widget
#
>>> 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

grizzled cloak
#

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

edgy kelp
#

shouldn't matter if they're only checking for the square

zealous widget
#

i feel like magic square is better than this

grizzled cloak
#

yeah probably but i didnt know they existed

zealous widget
#

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"

grizzled cloak
#

im still having some problems with my inline if statements...

zealous widget
#

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
grizzled cloak
#

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)```
zealous widget
#

that's a hell of a function

grizzled cloak
#

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

zealous widget
#

could shorten it more by changing the text and the grid names i suppose

#

i dunno how to improve the logic of it though

grizzled cloak
#

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

grizzled cloak
#

@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

zealous widget
#
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

marsh void
#

@zealous widget q=not q, but why not q^=1?

#

Since you don't need the booleans I can see

zealous widget
#

probably works

marsh void
#

No, it really does since 0^1 is 1 and 1^1 is 0

#

But lemme test anyway

zealous widget
#

it's not working

marsh void
#

hm

#

Weirdo

#

Where?

zealous widget
#

just keeps player 1 constantly, i need to switch between them

marsh void
#

hm

#

so q is switcher?

zealous widget
#

q is the current player

marsh void
#

mhm so 0 is 1 and 1 is 2?

zealous widget
#

yeah

marsh void
#

No it switches

#

For me

#

๐Ÿค”

zealous widget
#
>>> 0^0
 0
marsh void
#

^1

zealous widget
#

just stays at player1

marsh void
#

Lol

#

^1 it is

#

๐Ÿ˜…

#

So are you like really golfing or semi-golfing?

zealous widget
#

oh, i had q^=q

marsh void
#

Lmao

zealous widget
#

changed on the fly

#

i'm kinda golfing

#

while eating

marsh void
#

Also 0 looks really like O

#

maybe start with 1 and end with 9?

zealous widget
#
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!

marsh void
#

Hahaha!

#

I have that GitHub-like code font

zealous widget
#

i'm not sure what i'm using, i think just ubunto mono --- it doesn't differentiate between 0 and O very well either

marsh void
#
>>> '0'
'0'
>>> 'O'
'O'
#

Well, in my font there is a thing in a zero

maiden oak
#
            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

marsh void
#

why in esoteric?

gilded orchid
marsh void
#

Yeah

maiden oak
#

oh wait i thoughjt its help

#

noo

marsh void
#

rip

maiden oak
#

im just asking about syntax

marsh void
#

np, just move to appropriate channel

#

Oh

maiden oak
#

dw

#

ty

marsh void
#

I can see for loop in a dict

#

I am raising my eyebrow

zealous widget
#

if you can comp that dict, i'd be impressed

maiden oak
#

yup i need to use it

#

i mean

#

i know there is always other way

zealous widget
#

or you talking to style

maiden oak
#

wait

#

im dumb

#

sorry guys for prioblem

gilded orchid
#

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?

zealous widget
#

you're right, i can

#

good point, ever since i changed the grid names, just indexing a string would work

gilded orchid
#

although you'll have to put an int() everytime you reference it, so it might not save bytes

zealous widget
#

it's worth all the commas and colons

#

but string doesn't support del

#

hmm

gilded orchid
#

you could use list() around that string

#

but that might not save bytes then

#

then it'll suport del

zealous widget
#

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

marsh void
#
>>> 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)

zealous widget
#

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

grizzled cloak
#

Ha! For only 2x the chars you can have error handling!

zealous widget
#

not even 2x, it's like 6 extra characters or something

grizzled cloak
#

No I mean in my version hahaha

zealous widget
#

ah, oof

grizzled cloak
#

Oh man magic squares was really the way to go

#

But I do find mine more esoteric/unreadable

zealous widget
#

yeah, numpy is overkill

rugged sparrow
#
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
grizzled cloak
#

How many chars is that?

rugged sparrow
#

too many

grizzled cloak
#

Could you check?

zealous widget
#

looks like a lot

rugged sparrow
#

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

zealous widget
#

i think i prefer my dict version

#

just cause it crashes on incorrect moves

grizzled cloak
#

Ok thats 686chars

#

SoI at least im slightly shorter than that

rugged sparrow
#

lol

zealous widget
#

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)
>>> 
rugged sparrow
#

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
zealous widget
#

b=[*map(list,b)] saved some bytes with map

#

i never use map

grizzled cloak
#

Aw man

#

Ofc

#

You can use * and listcomp to convert the map obj to a list

zealous widget
#

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: 
formal sandal
#

If there are many maps, prints or ranges, you can reduce the amount of characters by storing them as one-character variables.

zealous widget
#

i have a lot of prints

#

p=print works?

formal sandal
#

yes

zealous widget
#

willdo

rugged sparrow
#
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

zealous widget
#

i dunno what it's doing

formal sandal
#
(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
edgy kelp
#

getting the max ๐Ÿ‘

zealous widget
#

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

rugged sparrow
#

b = [0,0,0,0,0,0,0,0,0]

#

and 0 is empty

edgy kelp
#

from looking at the string at the end, I don't want to know what it's doing ๐Ÿ˜„

rugged sparrow
#

1 is X

#

and 2 is O

zealous widget
#
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?

formal sandal
#

maybe turn 4 spaces into 1?

zealous widget
#

oh yeah

formal sandal
#

Are you using c only once?

zealous widget
#

yep

formal sandal
#
import itertools as z
...
z.combinations
#

It's shorter.

zealous widget
#

nice

#

(changed code above)

formal sandal
#

15 for -> 15for

edgy kelp
#

else'x'

formal sandal
#

'O'if q else 'X' ->'XO'[q]

zealous widget
#

that's a good one

formal sandal
#

(''.join(s)for s in b) -> map(''.join,b)

grizzled cloak
#

You think you could change m to a comp?

#

Does m follow some function?

zealous widget
#

i got rid of the break

#

lemme add the map

formal sandal
#

You make sure that everything works after every change, right?

#

Cause I can be dumb

#

(or just not considering some cases)

zealous widget
#

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

grizzled cloak
#

Oh Is m the magic sqr?

zealous widget
#

yep

#

it's the translator for the input to the magic square number

formal sandal
#

2*(i%3)
i%3<<1
single char, but still

zealous widget
#

oh is that byte shifting?

formal sandal
#

Yeah, bit shifting

zealous widget
#

oops, but

#

bit

#

rip typing

#

we can do it twice

#

have two 2*s

#

oh, i don't know how far it binds

formal sandal
#

-1-i//3<<1 == `(-1-i//3)<<1

#

so no

grizzled cloak
#

Why are you using a dict if they keys are 0-8?

formal sandal
#

good point

#

m=[*'2769516438']

zealous widget
#

because i delete items (so can't use string) and i depend on the indexing not changing when that happens

formal sandal
#

p[q]+=[m[i]];del m[i]
p[q]+=[m.pop(i)]

#

oh, ok

grizzled cloak
#

Str[i]="" does not work? Or is that longer

#

Yeah or pop

zealous widget
#

(indexing can't change)

grizzled cloak
#

Ah

formal sandal
#

you can just use a string.

#

oh, no, you can't

#

strings are immutable

zealous widget
#

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

formal sandal
#

Wait a minute.

#

Can't you just have a counter?

zealous widget
#

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

formal sandal
#

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
grizzled cloak
#

Well make it a string or list now

formal sandal
#

Also, why do you need this list and join construction in b?

#

Oh, got it

zealous widget
#

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

formal sandal
#

it seems to work with the things I've changed

#

oh

zealous widget
#

the elif not m part might need to change if you use a counter

#

->elif C==8

formal sandal
#

C>7 :)

zealous widget
#

i added a few bytes to redraw the board one last time to see the final position

formal sandal
#

Maybe create another string z and add 'removed' keys there?

zealous widget
#

what does ~ do? i think i can use it instead of -1-?

formal sandal
#

It's binary negation

#

not really

#

two's complement

zealous widget
#

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
formal sandal
#

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)

zealous widget
#

gonna end up using more bytes than the dict

formal sandal
#

Really?

zealous widget
#

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

grizzled cloak
#

Pretty trivial, but player0/1 instead of 1/2

#

Saves the+1

#

And dont think you need a fstring for "draw"

#

@zealous widget

zealous widget
#

oh, haha, how long have i had that

grizzled cloak
#

Hahaha

zealous widget
#

since the start

#

you think P0 and P1 is better?

grizzled cloak
#

Well it saves +1 two times

zealous widget
#

fair, i've sacrificed a few bytes for some niceties though, but i don't mind going to different player names

grizzled cloak
#

Can you post the updated one

zealous widget
#
"""
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

grizzled cloak
#

Does it matter?

zealous widget
#

nope

#

i changed it anyway

grizzled cloak
#

Remove the -1 from the input and move it into m

zealous widget
#

won't work, ruins the indexing of b

grizzled cloak
#

Oh

zealous widget
#

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'

grizzled cloak
#

I had that on mine and it is pretty annoying hah

#

Well. Imma head off. It's 2am

zealous widget
#

i'll be off soon as well, gn

grizzled cloak
#

Cya

sick hound
#

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```
sick hound
#

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

rugged sparrow
#

@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 ^

sick hound
#

tru

marsh void
#

Haha, glad my thing is used

#

Haha, why stuff is overridable

#

Like, 1-1 and we have O at 1

gilded orchid
#

map(int,list('276941438')) this is 4 bytes shorter for getting that list

marsh void
#

why would you need a list?

#

You can't pop from a map object

#

Well, m is shorter than this

icy blade
#
[*map(int,'276941438')]
[int(i)for i in'276941438']
zealous widget
#

nice guys, you saved a couple of bytes

zealous widget
#

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

grizzled cloak
#

what do we golf next?

#

i think we should golf a password generator haha

sick hound
#

<sarcasm>write a program that golfs python code

grizzled cloak
#

wut

sick hound
#

and then use the program to golf the program

#

</sarcasm>

zealous widget
#

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
grizzled cloak
#

impressive

zealous widget
#

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)
sick hound
#

what about golfing connect 4

zealous widget
#

connect 4 would be fun

edgy kelp
#

connect ~-5

zealous widget
#

how big is the connect 4 board

#

looks like 7X6

sick hound
#
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

zealous widget
#

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

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

zealous widget
#

you probably don't need to define the functions since we only use them once, poke

sick hound
#

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)

zealous widget
#

can you rename split? probably not because its a method?

sick hound
#

Never got round to checking win states

zealous widget
#

i'd probably check that all combinations of 4 moves satisfy one of 4 linear equations

teal drift
#

...

zealous widget
#

sorry /dev/log, you had a similar name to poke

teal drift
#

I do

zealous widget
#

i pressed enter too fast

teal drift
#

Lol

rugged sparrow
#

@zealous widget wdym rename split?

zealous widget
#

similar to how we golf repeated uses of other functions by assigning them to a single letter variable

#

is what i meant

brisk zenith
#

s=str.split

#

and then s("string")

rugged sparrow
#

beat me by one second lmao

brisk zenith
#

:D

zealous widget
#

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)
sick hound
#

oh right

zealous widget
#

another translate term maybe

sick hound
#
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()))
zealous widget
#

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

rugged sparrow
#
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

sick hound
#

does it help renaming split? since it's only used once

#

oh it's use twice

#

d

rugged sparrow
#

split was used twice

#

yea lol

#

oh wait i cant use i for items

sick hound
#

yeah that's not a function

zealous widget
#
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()))
rugged sparrow
#
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)))))```
zealous widget
#

try assigning everything all at once with unpacking

rugged sparrow
#

ah smart

sick hound
#

i think the only way to make it shorter substantially is to research the math into it and reimplement it entirely lol

rugged sparrow
#

true probably

zealous widget
#

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

zealous widget
#

though i can't think of a way to save code with any of it

sick hound
#

ill take a look once this fight is over

zealous widget
#

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

zealous widget
#

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]
grizzled cloak
#

"Found on the stack"

#

Love it

snow beacon
#

Whenever you encounter a bug, you can just pop off to the stack, as opposed to popping off the stack.

zealous widget
#

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
marsh void
#
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)

thin tusk
#

@marsh void showing un-obfuscated code first could help ๐Ÿ˜„

marsh void
#

Haha, sorry, don't have that thing ๐Ÿ˜…

#

I can try to write it out, though

sick hound
#

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
#

Woah nice

#

Thanks

#

Opinions on the encoder itself? @sick hound

sick hound
#

@marsh void obfuscated and unreadable, we have no idea what it is

marsh void
#

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'

crystal mica
#

Is it reversible?

marsh void
#

@crystal mica yeah, it is

#

There is the code for both encoding and decoding above

crystal mica
#

Nice

marsh void
#
>>> x = c('NeKitDS')
>>> x
'60be4dcf30143febf568739ba6239c17f57b58edefb9dd1'
>>> y = c('NeKit')
>>> y
'772ac0667661001701bca4b28e49c829d4'
>>> d(x)
'NeKitDS'
>>> d(y)
'NeKit'
formal sandal
#

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?

wind maple
#

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
>>>
odd blade
#

I think it's due to the way your other code works

#

aka the problem isn't what you asked

formal sandal
#

Yes, it's not just the exec.

#

I've sent the whole code, I'm using multiprocessing.

sick hound
#

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

grizzled cloak
#

Mp is really weird when it comes to scopes and sharing data across instances

pure dew
#

esoteric kinda

#

but not really in the common sense

#

more like "why would i ever need to do that programmatically"

sick hound
#

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

pure dew
#

i think it'd be fairly simple

sick hound
#

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
grizzled cloak
#

@sick hound id regex match for a equals someval

#

If you cant find that its not defined

#

Or search for "def a..."

#

Etc

rugged sparrow
#

@grizzled cloak that wont catch scoping. but tbh i dont see why anyone would want to do this

grizzled cloak
#

It would catch scoping if you check indents

#

But idk thats just rewriting python

#

Just try catch nameerror

rugged sparrow
#

yea

#

@sick hound why do you need to do this?

marsh void
#
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

grizzled cloak
#

Why are you execing a lot of code?

marsh void
#

Hm?

#

Yeah I do exec pretty long thing

grizzled cloak
#

Just so that its on one line?

marsh void
#

Yeah

#

๐Ÿ˜‰

#

Because while loops are meh to one-line

#

Is it actually possible?

rugged sparrow
#

yes

#

you can oneline any python code

grizzled cloak
#

Meh I feel like saving the 8 chars and having it on +1 line is better

rugged sparrow
#

ยฏ_(ใƒ„)_/ยฏ

#

onelining is fun

marsh void
#

def f(n,b,s=''):
while(n>0):n,x=divmod(n,b);s+=r(x)
return s[::-1]

#

Idk how to oneline

rugged sparrow
#

i can oneline that for you

#

one sec

marsh void
#

Haha thanks

#

@rugged sparrow this is r() if you need it r=lambda n:chr(n+48 if 0<=n<=9 else n+87)

rugged sparrow
#

๐Ÿ‘Œ

grizzled cloak
#

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

sick hound
#

@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.

grizzled cloak
#

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

sick hound
#

I just will make sure that this does not happen (two modules that both have a)

rugged sparrow
#

@marsh void whats some example input/output for f

marsh void
#

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 ^

rugged sparrow
#

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
marsh void
#

Oh yes

rugged sparrow
#

and im happy to explain any part of it

marsh void
#

Well, it slow as fuck if youโ€™ll excuse my French

rugged sparrow
#

hmm?

marsh void
#

Like, it is doing iter, append... well yeah it should be somewhat the same speed lol

rugged sparrow
#

yea...

#

so its prob not working right

#

one sec

marsh void
#

Haha, I am actually understanding almost everything in it

rugged sparrow
#

its working for me

#

btw

marsh void
#

It is pretty creative, I think

#

How you did it ๐Ÿ˜‰

#

Yeah, what is it?

rugged sparrow
#

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

marsh void
#

Yeah, getting it

#

wasnโ€™t a flag originally though, sentinel it was called lol

rugged sparrow
#

oh sentinel

#

i couldnt remember the term lol

marsh void
#

for s in iter(int,1):

#

Infinite loop of s = 0

#

๐Ÿ˜…

rugged sparrow
#

[*iter(int,1)]

marsh void
#

Lol

rugged sparrow
#

i think that might be the shortest possible infinite loop

#

without while

marsh void
#

Well, I donโ€™t think while True can kill the interpreter

#

Hm

rugged sparrow
#

yea while True is optimized

marsh void
#

Maybe there is 2-char builtin func name

rugged sparrow
#

maybe

marsh void
#

Nah, I think there isnโ€™t actually

rugged sparrow
#

id, but it needs an arg

marsh void
#

I love how one-lining people use tuples and indexes to add several instructions

rugged sparrow
#

it helps to keep things shorter

marsh void
#

Yeah actually

#

When do integers break in python?

#

I wanna test limits of my cipher thingy

rugged sparrow
#

max int is somewhere in sys

marsh void
#

The actual question is though, when does hex() break I think

rugged sparrow
#

i dont think it does till you hit max int size

marsh void
#

@rugged sparrow sys.int_info(bits_per_digit=30, sizeof_digit=4)

rugged sparrow
#

ah

marsh void
#

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

grizzled cloak
#

doubt anyone would figure that out

rugged sparrow
#

yea

grizzled cloak
#

@marsh void what is the code?

marsh void
#

The code?

grizzled cloak
#

to decode it

marsh void
#

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

rugged sparrow
#

@marsh void is r only used in f?

marsh void
#

a='{:x}'.format;b=int;e=''.join

#

Yeah I think

rugged sparrow
#

and is f only used in d

marsh void
#

just, donโ€™t

#

I know what you want to make

rugged sparrow
#

hahaha

marsh void
#

๐Ÿ˜„

#

temptation

rugged sparrow
#

im gonna do it

marsh void
#

Well

#

good luck I mean lol

grizzled cloak
#

hm?

rugged sparrow
#
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
marsh void
#

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

rugged sparrow
#
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

marsh void
#

Is import caching imported modules?

rugged sparrow
#

yes

marsh void
#

I mean __import__

rugged sparrow
#

oh no

#

it just returns the module object

#

globals().update({'textwrap':__import__('textwrap')}) is (pretty much at least) import textwrap

marsh void
#

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

rugged sparrow
#

haha

#

most of my oneline stuff is unreadable

#

especially the niche stuff. like try/except style stuff

#

and with x() as y

wild cairn
#

is there a way to await something in a lambda and get its return

rugged sparrow
#

yes i believe

#

someone wrote a discord bot in one line if you scroll up

nocturne saddle
#

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

rugged sparrow
#

ah

#

you can probably await somehow tho

wild cairn
#

but how do i get the return value of it

#

i can do .result but that can error

marsh void
#

.result() tbh

nocturne saddle
#

that will raise an exception if the task has not yet finished, though

marsh void
#

It also should raise exception if fut.exception() is not None iirc

wild cairn
#

remember i only have one line to use

sick hound
#

You can do try exceptd on one line

wild cairn
#

duno how well that will work in a lambda

rugged sparrow
#

@wild cairn I've written it lmao

#

It's tricky but doable

wild cairn
#

how?

rugged sparrow
#

I'm not at home rn but I'll send around 9ish

wild cairn
#

how long is that?

#

im probably in a differant timezone

rugged sparrow
#

Like an hr from now but tbh I just got home @wild cairn

#

@wild cairn there's the file ^

wild cairn
#

ok thanks

#

still doesnt help with my original question

rugged sparrow
#

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

grizzled cloak
#

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

sick hound
#

I think you can also do random.sample(letters, len(letters)) to randomly shuffle a list

rugged sparrow
#
(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))
sick hound
#

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))))

marsh void
#

((...), 2, 3)

grizzled cloak
#

i dont get it.

#

isnt ... the same as pass?

#

oh is it because it leaves the parentheses?

#

no, other stuff does that too

marsh void
#

it represents reference to an object in itself

grizzled cloak
#

hm?

#

but you can also just write Ellipsis

marsh void
#

Well

rugged sparrow
#
x = []
x.append(x)
print(x)
marsh void
#

lol, thatโ€™s not what I mean

#

Yeah, this

rugged sparrow
#

my code lets you do that with tuples

marsh void
#

Yep okhandbutflipped

rugged sparrow
#

it also supports negative indexing now

grizzled cloak
#
((Ellipsis), 1,1)
Out[31]: (Ellipsis, 1, 1)```
rugged sparrow
#

im currently trying to figure out how to make py (0,1,2)[0] = 1 work

marsh void
#

Lol

#

Well, you need to write __setitem__ but with some tricky way

#

Writing to a __dict__ wont work

rugged sparrow
#

yea i need to add it to the PyTuple_Type struct

marsh void
#

Yeah but how Thynk

rugged sparrow
#

ctypes

#

ยฏ_(ใƒ„)_/ยฏ

marsh void
#

lol

#

I am just doing my homework

rugged sparrow
#

lol

marsh void
#

Not funny

#

My literature teacher is such a dumbass ๐Ÿ˜”

rugged sparrow
#

im in lit rn lmao

marsh void
#

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

rugged sparrow
#

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)

calm rampart
#

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?

rugged sparrow
#

you called F instead of f

calm rampart
#

that was a typo

rugged sparrow
#

ah ok

#

i think it only looks in locals and globals

#

might be wrong tho

calm rampart
#

woo, got it to 'work' by creating a slot variable

>>> def f():
...  __name__='foo'
...  class B:
...   nonlocal __name__
...  return B
...
>>> f().__module__
'foo'```
rugged sparrow
#

nice

calm rampart
#

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

rugged sparrow
#

i guess that makes sense

calm rampart
#

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)

rugged sparrow
#

@brisk zenith hows the cpystructs module coming along?

brisk zenith
#

progress is sorta on and off, but i've had some really good ideas and stuff for how to implement it

rugged sparrow
#

Nice

#

it will probably make replacing dunder methods easier and thus my goal of making tuples traditionally mutable easier lmao

fallow cairn
#

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) :)

snow beacon
#

I don't understand. Is Rust the name of your own language, or do you mean the pre-existing compiled language?

fallow cairn
#

nom --> custom code generator --> cpython/etc

#

@snow beacon

snow beacon
#

So it's a rust program that compiles nom code to Python bytecode?

fallow cairn
#

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

sonic ginkgo
#

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

sick hound
#

@sonic ginkgo cool)
In which line does importlib work?

sonic ginkgo
#

oh

#

i forgot to delete that actually

sick hound
#
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:

  1. Using ast, program finds the classes that are called in this module.
  2. if the module has a name from the dictionary {module_name: import_from_here}, then program imports this module
  3. after all such imports, the program just imports the module x in 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.

sick hound
#

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?

sonic ginkgo
#

yep

#

oh yeah i guess i could have used ast to construct an import statement

#

there's more than one way to break python

rugged sparrow
sick hound
#

@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)
rugged sparrow
#

Look at ContextDecorator

sick hound
#

ok ty let me check it

sick hound
#

@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.

rugged sparrow
#

@sick hound what exactly are you trying to do?

sick hound
#
  1. I want to decorate a line of code, right in the code.
#
  1. it would be convenient to decorate several consecutive lines
    and thats all for now:)
rugged sparrow
#

That's not what decorators are supposed to do?

#

Just use with

#

So enter and exit

sick hound
#

@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')
rugged sparrow
#

That's always gonna throw a syntax error

sick hound
#

yep

#

moreover
I want it to work like this

@decorate
    print ('world')
    print ('!')
rugged sparrow
#

That also won't work

#

Without modifying the interpreter

sick hound
#

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 ('!')
rugged sparrow
#

So write it as a with statement

sick hound
#

@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.

snow beacon
#

Do you want to convert a pre-existing decorator into a context manager without rewriting the decorator?

sick hound
#

@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)

snow beacon
#

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.

sick hound
#

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

  1. get module name and lineno from where the Test class called (I will call it only from with statement)
    [with Test(): ...]

  2. get end line of this with statement

  3. so knowing start and end of code I get the whole with statement code source (string)

  4. create decorated temp function from the code that I got in (3)
    That is
    4.1) change first line to def my_temp_foo():
    4.2) add decorated line.

  5. just exec this function

sick hound
#

@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
stray needleBOT
brisk zenith
#

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

polar plover
#

this is gona be fun failing at xD

gilded orchid
#

oh wow, I completely forgot about that suggestion, might give this a shot later

brisk zenith
#

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

polar plover
#

this is going well, it's making "o" to chr(int(chr(int('110110', 2))+chr(int('1100110', 2)),16))

grizzled cloak
#

How obfuscated are we talking?

marsh void
#

Not obfuscated enough

polar plover
#

gona do more, this is just a start.

gilded orchid
#

make it so it can do bases other than 2 randomly

brisk zenith
#

@grizzled cloak about as obfuscated as you'd like. the more the better, though!

zealous widget
#
Enter string to obfuscate: hello
>>> len(obfuscated_string)
 3504

spits out a list of this many 2-tuples

marsh void
#

Haha, I see salt is very into image stuff

zealous widget
#

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

zealous widget
#

list -- > dict of dicts looks more obfuscated

marsh void
#

Yep

sonic ginkgo
#

everyone should just use Hy

#

the ultimate esoteric python exercise, except it's actually useful

rugged sparrow
#

@sonic ginkgo but writing terrible lambdas is so much more fun

pure dew
#

we should move to using actual lisp for better terrible lambdas

marsh void
#

Lol

edgy kelp
#

wondering if I should submit my 4 line obfuscator that'sโ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€Œโ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€Œโ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€Œโ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€Œโ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹ not really esoteric and pretty much only visual

snow beacon
#

The obfuscator readme is a bit ambiguous. Does our code need to produce python code? Or can it just 'encrypt' a string?

polar plover
#

@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

sick hound
edgy kelp
wild cairn
#

is there a way to subclass None?

#

cant do class a(type(None))

rugged sparrow
#

@wild cairn by changing the base class with ctypes

wild cairn
#

how?

rugged sparrow
#
from ctypes import py_object
class a:pass
py_object.from_address(id(a)+8).value = type(None)```
wild cairn
#

how can i do multiple subclasses with that?

rugged sparrow
#

tbh i dont know

#

also thats not quite how to change it

wild cairn
#

seems to work

rugged sparrow
#

ยฏ_(ใƒ„)_/ยฏ