#esoteric-python
1 messages · Page 35 of 1
It limit to certain data type otherwise it will fail I think
Or maybe first one doesn't matter 🤔
I am surprised that it work with anything
or nvm
yeah, it would work
since i==0
so it just completely bypass it if it just have 1 thing
i mean..
f([4],[[], [1], [2], {}, {1}, <function <lambda> at 0x000001607022EA20>])='G'
g([4],[[], [1], [2], {}, {1}, <function <lambda> at 0x000001607022EA20>])='G'
im not sure how to get the ,,other" keypad characters from the 2nd argument
!e
print(list(zip([1],[1,2,3])))
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
[(1, 1)]
yeah, since x only have 1 element
so zip will only have length of 1
so also bypass check
it should crash if you do
f([1,1], [[], [1]])
ig
yep
And python output the most confusing error message I have ever seen 🤣
def g(x, y):
table = {
0: [" "],
2: ["A", "B", "C"],
3: ["D", "E", "F"],
4: ["G", "H", "I"],
5: ["J", "K", "L"],
6: ["M", "N", "O"],
7: ["P", "Q", "R", "S"],
8: ["T", "U", "V"],
9: ["W", "X", "Y", "Z"],
}
d = [
table[d[1]][
(
[
(i, b[0])
for i, b in enumerate(zip(x, y))
if i == 0 or b[0] != x[i - 1] or b[1] > y[i - 1] + 0.5
]
+ [(len(x),)]
)[i + 1][0]
- d[0]
- 1
]
for i, d in enumerate(
[
(i, b[0])
for i, b in enumerate(zip(x, y))
if i == 0 or b[0] != x[i - 1] or b[1] > y[i - 1] + 0.5
]
)
]
return "".join(d)
funny formatting doesnt help me understand it yet
🤣
You shouldn't really use d outside when d is in the list comprehension
Even tho they most likely won't disturb each other
And I successfully make 2 people in another server hate one-linear (possibly)
def g(x, y):
table = {
0: [" "],
2: ["A", "B", "C"],
3: ["D", "E", "F"],
4: ["G", "H", "I"],
5: ["J", "K", "L"],
6: ["M", "N", "O"],
7: ["P", "Q", "R", "S"],
8: ["T", "U", "V"],
9: ["W", "X", "Y", "Z"],
}
thing = [
table[b_item[1]][
(
[
(c_idx, c_item[0])
for c_idx, c_item in enumerate(zip(x, y))
if c_idx == 0 or c_item[0] != x[c_idx - 1] or c_item[1] > y[c_idx - 1] + 0.5 # same thing?
]
+ [(len(x),)]
)[b_idx + 1][0]
- b_item[0]
- 1
]
for b_idx, b_item in enumerate(
[
(i_idx, i_item[0])
for i_idx, i_item in enumerate(zip(x, y))
if i_idx == 0 or i_item[0] != x[i_idx - 1] or i_item[1] > y[i_idx - 1] + 0.5 # same thing?
]
)
]
return "".join(thing)
im currently tryingg to understand that condition
Ok lol
And for the comment, yes, they are same thing
But because I need to make it fully one-linear without semi-colon, so I cannot use a variable to store the result
So I put those things inside
and no way for walrus yeah
def g(x, y):
table = {
0: [" "],
2: ["A", "B", "C"],
3: ["D", "E", "F"],
4: ["G", "H", "I"],
5: ["J", "K", "L"],
6: ["M", "N", "O"],
7: ["P", "Q", "R", "S"],
8: ["T", "U", "V"],
9: ["W", "X", "Y", "Z"],
}
something = [
(idx, pair[0])
for idx, pair in enumerate(zip(x, y))
if idx == 0
or pair[0] != x[idx - 1]
or pair[1] > y[idx - 1] + 0.5
]
thing = [
table[s_item[1]][(something + [(len(x),)])[s_idx + 1][0] - s_item[0] - 1]
for s_idx, s_item in enumerate(something)
]
return "".join(thing)
okay thats great
And now, you quite fully decompressed to when I code it
ok right nice so i take idx and the first item in pair guaranteed for the first pair and then if the first item is.. not equal to the item in uhh, the first item in the previous pair or the 2nd item is higher than the (second item in previous pair + 0.5) [well, not really previous, negative indexes and stuff]
f([2, 2, 2],[3, 2, 3])='BA'
g([2, 2, 2],[3, 2, 3])='BA'
thats interesting i finally got new letter
🤣
alright so x will definitely be [4, 2, 7, 7, 9, 0, 2, 4, 7, 8, 4, 7, 3, 2, 9]
now on to the second uhh magic thing
hmmh
Read this on how 3 element on x only result in 2 character
yeah because the conditional
So you have to consider that as well
the only thing i am sure in right now is that x[0] needs to be 4 lmao
Yes, that true 🤣
i need help
menu={
"Baja Taco": 4.00,
"Burrito": 7.50,
"Bowl": 8.50,
"Nachos": 11.00,
"Quesadilla": 8.50,
"Super Burrito": 8.50,
"Super Quesadilla": 9.50,
"Taco": 3.00,
"Tortilla Salad": 8.00
}
while True:
try:
item = input("Item: ")
if item in menu:
order=0.00
order=float(order)+float(menu[item])
else:
break
except EOFError:
break
if item in menu:
print("Total: $" + str(order))
else:
print("")
im getting a
why #esoteric-python ?
menu={
"Baja Taco": 4.00,
"Burrito": 7.50,
"Bowl": 8.50,
"Nachos": 11.00,
"Quesadilla": 8.50,
"Super Burrito": 8.50,
"Super Quesadilla": 9.50,
"Taco": 3.00,
"Tortilla Salad": 8.00
}
while True:
try:
item = input("Item: ")
if item in menu:
order=0.00
order=float(order)+float(menu[item])
else:
break
except EOFError:
break
if item in menu:
print("Total: $" + str(order))
else:
print("")
idk what other server
oh ok thx
this place is for cursed code
Yeah lol
Like this #esoteric-python message
def g(x, y):
table = {
0: [" "],
# 1 missing because idk
2: ["A", "B", "C"],
3: ["D", "E", "F"],
4: ["G", "H", "I"],
5: ["J", "K", "L"],
6: ["M", "N", "O"],
7: ["P", "Q", "R", "S"],
8: ["T", "U", "V"],
9: ["W", "X", "Y", "Z"],
}
something = [
(idx, pair[0])
for idx, pair in enumerate(zip(x, y))
if idx == 0
or pair[0] != x[idx - 1]
or pair[1] > y[idx - 1] + 0.5
]
thing = [
table[s_item[1]][
(
keyidx :=
(something + [(len(x),)])[s_idx + 1][0]
- (s_item[0] + 1) # very interesting expression
)
]
for s_idx, s_item in enumerate(something)
]
return "".join(thing)
hmmh
You can print something out from the code which might help 🤔
yeah probally
Since you have decompressed it
the len(x) when calculating keyidx is confusing me very much
this is oddly familiar to a nokia or any old mobile phone typing system
yeah it is a keypad
but the input output correlation is very weird
currently i have
p(
[4, 4, 2, 7, 7, 9],
[2, 2, 2, 7, 8, 7],
)
which gives me
something=[(0, 4), (2, 2), (3, 7), (4, 7), (5, 9)]
s_idx=0 s_item=(0, 4) part=(2, 2) -> keyidx=1 which is ((2, 2)[0] -> 2) - (((0, 4)[0] -> 0)+1)
s_idx=1 s_item=(2, 2) part=(3, 7) -> keyidx=0 which is ((3, 7)[0] -> 3) - (((2, 2)[0] -> 2)+1)
s_idx=2 s_item=(3, 7) part=(4, 7) -> keyidx=0 which is ((4, 7)[0] -> 4) - (((3, 7)[0] -> 3)+1)
s_idx=3 s_item=(4, 7) part=(5, 9) -> keyidx=0 which is ((5, 9)[0] -> 5) - (((4, 7)[0] -> 4)+1)
s_idx=4 s_item=(5, 9) part=(6,) -> keyidx=0 which is ((6,)[0] -> 6) - (((5, 9)[0] -> 5)+1)
thing=['H', 'A', 'P', 'P', 'W']
f([4, 4, 2, 7, 7, 9],[2, 2, 2, 7, 8, 7])='HAPPW'
g([4, 4, 2, 7, 7, 9],[2, 2, 2, 7, 8, 7])='HAPPW'
i dont understand how to uhh get a different letter
Ok, do you know what is the thing on y
kinda? i need to increase keyidx to 2
Try to describe it
like how
Ok, I don't think you know what y is then 🤣
you like select the 9th keypad button and get the 3rd character
Ok, y accept a list of float data
ah you meant the y argument
Now try something
not the letter y
Yeah
i actually got y right now
p(
[4, 4, 2, 7, 7, 9, 9, 9],
[2, 2, 2, 7, 8, 9, 9, 9],
)
gives me
thing=['H', 'A', 'P', 'P', 'Y']
i think i understand it
Probably 🤔
yeah i do
p(
[4, 4, 2, 7, 7, 9, 9, 9, 0, 2, 2, 4, 4, 4, 7, 7, 7, 8, 4, 4, 7, 7, 7, 7, 3, 2, 9, 9, 9],
[2, 2, 2, 7, 8, 9, 9, 9, 0, 2, 2, 4, 4, 4, 7, 7, 7, 8, 4, 4, 7, 7, 7, 7, 3, 2, 9, 9, 9],
)
thing=['H', 'A', 'P', 'P', 'Y', ' ', 'B', 'I', 'R', 'T', 'H', 'S', 'D', 'A', 'Y']
this is genius
No S
uh right my english is funny
p(
[4, 4, 2, 7, 7, 9, 9, 9, 0, 2, 2, 4, 4, 4, 7, 7, 7, 8, 4, 4, 3, 2, 9, 9, 9],
[2, 2, 2, 7, 8, 9, 9, 9, 0, 2, 2, 4, 4, 4, 7, 7, 7, 8, 4, 4, 3, 2, 9, 9, 9],
)
thing=['H', 'A', 'P', 'P', 'Y', ' ', 'B', 'I', 'R', 'T', 'H', 'D', 'A', 'Y']
By follow this rule:
- The first element of
ymust be 0 - Each element in
ymust at least increment by 0.1 than the last value
What is the minimum value for the last element of y to get "HAPPY BIRTHDAY"
And also, all value in y must be 1 decimal point
Like you cannot have 0.91
Only 0.9 or 1
i see
i just put a bunch of zeroes
0
unless negatives are allowed
must at least increnment by 0.1 and start with 0
oh
lol
well there's only one that needs a 0.6 increment so
So, putting all 0 probably won't work either
2.7
Type the whole answer so it would be easy to verify
>>> g([4,4,2,7,7,9,9,9,0,2,2,4,4,4,7,7,7,8,4,4,3,2,9,9,9],[0,0.1,0.2,0.3,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7])
'HAPPY BIRTHDAY'
idk
yeah im basically doing the same thing rn
gg
You guys solve the question
I will just throw the question to people that barely learn python 🤣
And they would go crazy
i feel like the >0.5 increment was just to distinguish the consecutive characters
Yeah
i think i understandn it now :D
im trying to represent the keypresses funnier with the data
p(
[*(4,)*2 , 2 , *(7,)*2 , *(9,)*3 , 0 , *(2,)*2 , *(4,)*3 , *(7,)*3 , 8 , *(4,)*2 , 3 , 2 , *(9,)*3],
[*(0,0.1), 0.2, *(0.3, 0.9), *(1.0, 1.1, 1.2), 1.3, *(1.4, 1.5), *(1.6, 1.7, 1.8), *(1.9,2.0,2.1), 2.2, *(2.3,2.4), 2.5, 2.6, 2.7 ],
)
like that
lol
this was really interesting problem thanks
def keypad(inp, dist):
keypad = {
0: [" "],
# there's no ASCII characters for 1 on a keypad
2: ["A", "B", "C"],
3: ["D", "E", "F"],
4: ["G", "H", "I"],
5: ["J", "K", "L"],
6: ["M", "N", "O"],
7: ["P", "Q", "R", "S"],
8: ["T", "U", "V"],
9: ["W", "X", "Y", "Z"],
}
idx_key_pair = [
(idx, key)
for idx, (key, dist_from_prev) in enumerate(zip(inp, dist))
# add if:
if idx == 0 # - just started
or key != inp[idx - 1] # - key is different
or dist_from_prev > dist[idx - 1] + 0.5 # - distance from previous key is > 0.5
]
chars = [
keypad[key][
# get the character based on the amount of keypresses
# between the next one (or the length of the input)
# like an old keypad
idx_key_pair[s_idx + 1][0] - idx
if s_idx + 1 < len(inp) else
len(inp) - idx
]
for s_idx, (idx, key) in enumerate(idx_key_pair)
]
return "".join(chars)
de-esotericized, commented
teamwork
now i'm gonna go golf it later
i have school first
i hab school in 7 hrs too
i might need to go sleep
more golf
lambda x,y: ''.join([{0: [' '],2:['A','B','C'],3:['D','E','F'],4:['G','H','I'],5:['J','K','L'],6:['M','N','O'],7:['P','Q','R','S'],8:['T','U','V'],9:['W','X','Y','Z']}[d[1]][d[2][i+1]-d[0]-1]for i,d in enumerate([(i,b[0],[i for i,b in enumerate(zip(x,y))if i==0 or b[0]!=x[i-1] or b[1]>y[i-1]+0.5]+[len(x)])for i,b in enumerate(zip(x,y))if i==0 or b[0]!=x[i-1] or b[1]>y[i-1]+0.5])])
and more
lambda I,L: ''.join([{0:[chr(0x20)],2:[chr(I) for I in [0o101,0x42,0b1000011]],3:[chr(i+3) for i in [0o101,0x42,0b1000011]],4:[chr(L+6) for L in [0o101,0x42,0b1000011]],5:[chr(I+9) for I in [0o101,0x42,0b1000011]],6:[chr(l+12) for l in [0o101,0x42,0b1000011]],7:[chr(l+15) for l in [0o101,0x42,0b1000011,0o104]],8:[chr(L+19) for L in [0o101,0x42,0b1000011]],9:[chr(i+22) for i in [0o101,0x42,0b1000011,0b1000100]]}[l[1]][l[2][i]-l[0]-1]for i,l in enumerate([(i,I[i],[i for i in range(1,min(len(I),len(L)))if (I[i]!=I[i-1])|(L[i]>L[i-1]+0.5)]+[len(I)])for i in range(len(list(zip(I,L))))if (i==0)|(I[i]!=I[i - 1])|(L[i]>L[i-1]+0.5)])])
Using confusing variable name, repeated variable name in list comprehension, reduce duplicate part in real code, remove or key word, obfuscate dictionary with list comprehensive with integer prefix
This probably didn't really increase much difficulty
But annoy people
And it only consist of 4 variable: i l I L
haha
Yeah, at least what I know
you know what you could do
Oh wait, I can also obfuscate the dictionary key
!e
print(~-0)
this instead of x-1
@karmic pumice :white_check_mark: Your 3.12 eval job has completed with return code 0.
-1
~x (for ints) = -(x+1) #****
Ok
so ~-2 is -(-2+1) -> 2-1 -> 1
!e
print(~-10)
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
9
ok nices
instead of l[1] you could do l[-~int()]
!e
print(~-0b1010)
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
9
ok, great
and thing[0] -> thing[int()] maybe
or thing[type(0)()]
or thing[not __name__=="__main__"]
ok, need to learn more about esoteric lol
!e
print(~-len([('x',['d',('f',['u',('n',['n',('y',[([()])])])])])]))
@karmic pumice :white_check_mark: Your 3.12 eval job has completed with return code 0.
0
you can start expressing numbers as peano numbers i guess with successors
!e
s=lambda x=0:x+1
print(s(s(s(s()))))
!e My favourite way to get number 3: ```py
import _testcapi
print(_testcapi.the_number_three)
oops
:(
@karmic pumice :white_check_mark: Your 3.12 eval job has completed with return code 0.
4
>>> import _testcapi
>>> print(_testcapi.the_number_three)
3
lmao
does it have other the numbers
In [27]: print([t for t in dir(_testcapi) if t.startswith('the_number')])
['the_number_three']
😭
the 3 is special enough
lambda I,L: str().join([{~-1:[chr(0x20)],~-0b11:[chr(I) for I in [0o101,0x42,0b1000011]],(~-0+0xA)//0b11:[chr(i+3) for i in [0o101,0x42,0b1000011]],0b100:[chr(L+6) for L in [0o101,0x42,0b1000011]],0xA//~-0b11:[chr(I+9) for I in [0o101,0x42,0b1000011]],(~-4)*(~-3):[chr(l+12) for l in [0o101,0x42,0b1000011]],0b111:[chr(l+15) for l in [0o101,0x42,0b1000011,0o104]],0o10:[chr(L+~-20) for L in [0o101,0x42,0b1000011]],(~-0b100)**2:[chr(i+ord('\x16')) for i in [0o101,0x42,0b1000011,0b1000100]]}[l[~-0b10]][~-0+l[0b10][i]-l[int()]]for i,l in enumerate([(i,I[i],[i for i in range(1,min(len(I),len(L)))if (I[i]!=I[i-1])|(L[i]>L[i-1]+(~-0b10)/0b10)]+[len(I)])for i in range(len(list(zip(I,L))))if (i==int())|(I[i]!=I[~-int()+i])|(L[i]>L[~-(not __name__=="__main__")+i]+(~-0b10)/0b10)])])
Discord syntax highlight is hating me lol
its pretty good on PC and awful on mobile
Yeah
And also I am making the code slower and slower
Because it have to calculate all those stuff
Mhh really? I thought it gonna recalculate the dictionary on each iteration
well it does build the dict each time, but the stuff from which it builds it is constant
Oh ok
i think if you care enough you could write the table as an argument with a default value
lambda I,L,t={}:
but then write it normally probally 🤷 kinda incompatible ideas
So if I make it access a variable from the iteration to do a pointless calculation, it have to recalculate every time?
Like +i-i
no
lists & list comps aren't constant
that part - sure, but im talking about the added integer calculation stuff
~-1, ~-0b11
Oh nah, I was talking about the entirety of the stupidly long dictionary
an easy way to check is to use dis
all of that stuff is calculated at bytecode compile time btw, it doesnt get calculated even at first call
!e
f=lambda I,L: str().join([{~-1:[chr(0x20)],~-0b11:[chr(I) for I in [0o101,0x42,0b1000011]],(~-0+0xA)//0b11:[chr(i+3) for i in [0o101,0x42,0b1000011]],0b100:[chr(L+6) for L in [0o101,0x42,0b1000011]],0xA//~-0b11:[chr(I+9) for I in [0o101,0x42,0b1000011]],(~-4)*(~-3):[chr(l+12) for l in [0o101,0x42,0b1000011]],0b111:[chr(l+15) for l in [0o101,0x42,0b1000011,0o104]],0o10:[chr(L+~-20) for L in [0o101,0x42,0b1000011]],(~-0b100)**2:[chr(i+ord('\x16')) for i in [0o101,0x42,0b1000011,0b1000100]]}[l[~-0b10]][~-0+l[0b10][i]-l[int()]]for i,l in enumerate([(i,I[i],[i for i in range(1,min(len(I),len(L)))if (I[i]!=I[i-1])|(L[i]>L[i-1]+(~-0b10)/0b10)]+[len(I)])for i in range(len(list(zip(I,L))))if (i==int())|(I[i]!=I[~-int()+i])|(L[i]>L[~-(not __name__=="__main__")+i]+(~-0b10)/0b10)])])
import dis
dis.dis(f)
@karmic pumice :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1 0 RESUME 0
002 | 2 LOAD_GLOBAL 1 (NULL + str)
003 | 12 CALL 0
004 | 20 LOAD_ATTR 3 (NULL|self + join)
005 | 40 LOAD_GLOBAL 5 (NULL + enumerate)
006 | 50 LOAD_GLOBAL 7 (NULL + range)
007 | 60 LOAD_GLOBAL 9 (NULL + len)
008 | 70 LOAD_GLOBAL 11 (NULL + list)
009 | 80 LOAD_GLOBAL 13 (NULL + zip)
010 | 90 LOAD_FAST 0 (I)
011 | 92 LOAD_FAST 1 (L)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/SP2B2X5VS35S4EPZJB567NPBPU
!e ```py
f=lambda I,L: str().join([{~-1:[chr(0x20)],~-0b11:[chr(I) for I in [0o101,0x42,0b1000011]],(~-0+0xA)//0b11:[chr(i+3) for i in [0o101,0x42,0b1000011]],0b100:[chr(L+6) for L in [0o101,0x42,0b1000011]],0xA//~-0b11:[chr(I+9) for I in [0o101,0x42,0b1000011]],(~-4)*(~-3):[chr(l+12) for l in [0o101,0x42,0b1000011]],0b111:[chr(l+15) for l in [0o101,0x42,0b1000011,0o104]],0o10:[chr(L+~-20) for L in [0o101,0x42,0b1000011]],(~-0b100)**2:[chr(i+ord('\x16')) for i in [0o101,0x42,0b1000011,0b1000100]]}[l[~-0b10]][~-0+l[0b10][i]-l[int()]]for i,l in enumerate([(i,I[i],[i for i in range(1,min(len(I),len(L)))if (I[i]!=I[i-1])|(L[i]>L[i-1]+(~-0b10)/0b10)]+[len(I)])for i in range(len(list(zip(I,L))))if (i==int())|(I[i]!=I[~-int()+i])|(L[i]>L[~-(not name=="main")+i]+(~-0b10)/0b10)])])
import dis
dis.dis(f)
@versed eagle :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1 0 RESUME 0
002 | 2 LOAD_GLOBAL 1 (NULL + str)
003 | 12 CALL 0
004 | 20 LOAD_ATTR 3 (NULL|self + join)
005 | 40 LOAD_GLOBAL 5 (NULL + enumerate)
006 | 50 LOAD_GLOBAL 7 (NULL + range)
007 | 60 LOAD_GLOBAL 9 (NULL + len)
008 | 70 LOAD_GLOBAL 11 (NULL + list)
009 | 80 LOAD_GLOBAL 13 (NULL + zip)
010 | 90 LOAD_FAST 0 (I)
011 | 92 LOAD_FAST 1 (L)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/UBVHGIDPADRZYU53LXMGSSCORI
lmao
!e
import dis
a = lambda I,L: str().join([{~-1:[chr(0x20)],~-0b11:[chr(I) for I in [0o101,0x42,0b1000011]],(~-0+0xA)//0b11:[chr(i+3) for i in [0o101,0x42,0b1000011]],0b100:[chr(L+6) for L in [0o101,0x42,0b1000011]],0xA//~-0b11:[chr(I+9) for I in [0o101,0x42,0b1000011]],(~-4)*(~-3):[chr(l+12) for l in [0o101,0x42,0b1000011]],0b111:[chr(l+15) for l in [0o101,0x42,0b1000011,0o104]],0o10:[chr(L+~-20) for L in [0o101,0x42,0b1000011]],(~-0b100)**2:[chr(i+ord('\x16')) for i in [0o101,0x42,0b1000011,0b1000100]]}[l[~-0b10]][~-0+l[0b10][i]-l[int()]]for i,l in enumerate([(i,I[i],[i for i in range(1,min(len(I),len(L)))if (I[i]!=I[i-1])|(L[i]>L[i-1]+(~-0b10)/0b10)]+[len(I)])for i in range(len(list(zip(I,L))))if (i==int())|(I[i]!=I[~-int()+i])|(L[i]>L[~-(not __name__=="__main__")+i]+(~-0b10)/0b10)])])
dis.dis("a([4,4,2,7,7,9,9,9,0,2,2,4,4,4,7,7,7,8,4,4,3,2,9,9,9],[0,0.1,0.2,0.3,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7])")
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 PUSH_NULL
004 | 4 LOAD_NAME 0 (a)
005 | 6 BUILD_LIST 0
006 | 8 LOAD_CONST 0 ((4, 4, 2, 7, 7, 9, 9, 9, 0, 2, 2, 4, 4, 4, 7, 7, 7, 8, 4, 4, 3, 2, 9, 9, 9))
007 | 10 LIST_EXTEND 1
008 | 12 BUILD_LIST 0
009 | 14 LOAD_CONST 1 ((0, 0.1, 0.2, 0.3, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7))
010 | 16 LIST_EXTEND 1
011 | 18 CALL 2
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/H2V3GFKEKLIUG4OZNJIX2PXYLY
ahaha
Lmao, it doesn't show lambda
wdym
I thought it going to show what happen inside the function when it run
nope
for that you'd disassemble the function itself, not a call to it
!e
import dis
def a():
print("Hi!")
dis.dis("a()")
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 PUSH_NULL
004 | 4 LOAD_NAME 0 (a)
005 | 6 CALL 0
006 | 14 RETURN_VALUE
nope
if passed a string, it compiles that string
and then disassembles
!e
def f():
pass # load const None return whatever
# yeah
import dis
dis.dis(f)
@karmic pumice :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1 0 RESUME 0
002 |
003 | 2 2 RETURN_CONST 0 (None)
there's no way for it to actually do that
do dis.dis(a)
!e
import dis
a = lambda I,L: str().join([{~-1:[chr(0x20)],~-0b11:[chr(I) for I in [0o101,0x42,0b1000011]],(~-0+0xA)//0b11:[chr(i+3) for i in [0o101,0x42,0b1000011]],0b100:[chr(L+6) for L in [0o101,0x42,0b1000011]],0xA//~-0b11:[chr(I+9) for I in [0o101,0x42,0b1000011]],(~-4)*(~-3):[chr(l+12) for l in [0o101,0x42,0b1000011]],0b111:[chr(l+15) for l in [0o101,0x42,0b1000011,0o104]],0o10:[chr(L+~-20) for L in [0o101,0x42,0b1000011]],(~-0b100)**2:[chr(i+ord('\x16')) for i in [0o101,0x42,0b1000011,0b1000100]]}[l[~-0b10]][~-0+l[0b10][i]-l[int()]]for i,l in enumerate([(i,I[i],[i for i in range(1,min(len(I),len(L)))if (I[i]!=I[i-1])|(L[i]>L[i-1]+(~-0b10)/0b10)]+[len(I)])for i in range(len(list(zip(I,L))))if (i==int())|(I[i]!=I[~-int()+i])|(L[i]>L[~-(not __name__=="__main__")+i]+(~-0b10)/0b10)])])
dis.dis(a)
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 2 0 RESUME 0
002 | 2 LOAD_GLOBAL 1 (NULL + str)
003 | 12 CALL 0
004 | 20 LOAD_ATTR 3 (NULL|self + join)
005 | 40 LOAD_GLOBAL 5 (NULL + enumerate)
006 | 50 LOAD_GLOBAL 7 (NULL + range)
007 | 60 LOAD_GLOBAL 9 (NULL + len)
008 | 70 LOAD_GLOBAL 11 (NULL + list)
009 | 80 LOAD_GLOBAL 13 (NULL + zip)
010 | 90 LOAD_FAST 0 (I)
011 | 92 LOAD_FAST 1 (L)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ESNSEJG5QASGFNAG2FYRAGGYQA
since what the name refers to is unknown until runtime
probably you should use your own repl or #bot-commands if you want to do this a lot
Nah, I was literally gonna go off and sleep
The only reason I run it here is I put my laptop on sleep mode
Can i reassign var without =,@and ()?
yeah I think so
lemme make an example rq
it should just be the decorator chaining stuff, right?
Im sorry i forgot that is not possible too
not sure then
re.escape('\\(~}?>{&/%)<$|*=#!-+'0123456789;@, '` it would be like this for the regex
!e ```py
import main
for main.variable in ["value"]: ...
print(variable)
@versed eagle :white_check_mark: Your 3.12 eval job has completed with return code 0.
value
til you can do attribute access in for loops like that wtf
you can also do indexing
How come you get this idea😭
you asked for it
.
Yeah but i mean is i didnt expect using for loops for this. Youre genius!😭
that's a smart way to avoid the assignment target being explicitly stated
bravo
Anyhow, what I'm here for is that I'm trying to implement SKI in python
Obviously, Python is eager, so the following won't work:
I = lambda x:x
K = lambda x:lambda y:x
S = lambda x:lambda y:lambda z: x(z)(y(z))
So I thought "hmmm. maybe thunks are a way to implement this"
Specifically, to implement lazy evaluation
At first I did this:
class Thunk:
def __init__(self, f, arg):
self.f = f
self.arg = arg
def __call__(self): # thunks take no arguments
return self.f(self.arg)
But that's stupid, because that's just one of the following (which? I think it's the second)
lambda f,arg:lambda:f(arg)
lambda f,arg:lambda f=f,arg=arg:f(arg)
And well, that's where I got stuck
what's ski?
The SKI combinator calculus is a combinatory logic system and a computational system. It can be thought of as a computer programming language, though it is not convenient for writing software. Instead, it is important in the mathematical theory of algorithms because it is an extremely simple Turing complete language. It can be likened to a reduc...
why doesn't this work?
because python is strictly evaluated
why does that mean it won't work
because lambda calculus (which is what I am trying to implement here) uses a lazy evaluation model, for which Python's strict evaluation (of expressions) isn't suitable
so I need to implement lazy expression evaluation
which I think (?) can be done in a strict-evaluation situation using thunks?
do you have an example in which that makes a difference?
not to hand, my lambda calculus isn't great
but off the top of my head - in strict evaluation, the fixpoint combinator is an infinite loop
in lazy evaluation it isn't
i think
is it not?
the recursion isnt bounded by anything
for a lot of this I'm going off a conversation I had months ago in the esolangs discord where they told me this didn't work
by a very skilled functional programmer
maybe I should head over there and ask them again
i think i understand what you're wanting
you're wanting to be able to reduce functions step by step yes?
such that SII(SII) reduces back down to SII(SII) but stops there
did i understand right?
maybe?
the combinators should take thunks (unevaluated expressions...?) and return the same, I presume
Is there any python docs about this?
for loops have structure
for assignment_target in iterable:
...
and they turn that iterable into an iterator
then run assignment_target = next(iterator)
so it's just doing __main__.variable = "value"
probably
can i golf https://open.kattis.com/problems/romanholidays further than this?
r=[(H+T+O).replace(' ','')for H in" .C.CC.CCC.CD.D.DC.DCC.DCCC.CM".split('.')for T in" .X.XX.XXX.XL.L.LX.LXX.LXXX.XC".split('.')for O in" .I.II.III.IV.V.VI.VII.VIII.IX".split('.')]
v=sorted(r)
for n in[int(input())for i in range(int(input()))]:a,b=divmod(n,1000);b=r[b];print([946*a+v.index(b),-54*a-1000+v.index(b)][bool(b and b[0]in'XV')])
i mean yes i have gotten shortest but just posting here for fun
# first 1000 roman numerals
r=[(H+T+O).replace(' ','')for H in" .C.CC.CCC.CD.D.DC.DCC.DCCC.CM".split('.')
for T in" .X.XX.XXX.XL.L.LX.LXX.LXXX.XC".split('.')
for O in" .I.II.III.IV.V.VI.VII.VIII.IX".split('.')]
v=sorted(r) # sorted
for n in[int(input())for i in range(int(input()))]: # loop thru input
a,b=divmod(n,1000) # remove all Ms from the roman numeral for now
b=r[b] # get the actual roman
# simple multiplication as
# M is at index 945, MC at 946 etc, then MM is at 1892 and MMC 1893
# XXXVIII is at index -1, MXXXVIII -55, MMXXXVIII -109 etc
if b and b[0]in'XV':print(-54*a-1000+v.index(b)) # return negative index
else:print(946*a+v.index(b)) # return positive index
heres readable version yes
Any ideas on how to implement (hack) an automatically unpacked record type?
Basically I want to be able to do this: (lambda x, y: x + y)((lambda: xy)()) and auto-magically destructure xy similar to how multiple comma separated return values work in Go. I want to avoid decorating the outer function.
!e
xy = (1,2)
print((lambda x, y: x + y)(*(lambda: xy)()))
? not sure if thats what you want
@dreamy bridge :white_check_mark: Your 3.12 eval job has completed with return code 0.
3
Not exactly. I'm essentially trying to store **kwargs in a variable; this expression throws a syntax error in most circumstances though. I suspect there's no way to do what I want without some absurd hacks.
yea i've never been able to store a variable with lambda before if thats what you want
Maybe this is more illustrative of what I want.
xy = *(2, 3) # this is the black magic i'm trying to replicate
assert (lambda x, y: x + y)(xy) == 5
!e
print(type(True).real.class.init_subclass().sizeof()*4+1)
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
65
nice
!e py print(type(True).real.__class__.__init_subclass__().__sizeof__().__mul__(4).__add__(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__()))) kind of a lazy extra obf layer but yewah
@unique heath :white_check_mark: Your 3.12 eval job has completed with return code 0.
65
202b ```py
f=lambda x,y,i=0,j=-1:bool(t:=[(j,a)for a,b in zip(x,y)if(j:=j+1)<1 or b>.5+y[j-1]or a-x[j-1]])''.join([" ",0,"ABC DEF GHI JKL MNO PQRS TUV WXYZ".split()][a][[*t,[len(x)]][i:=i+1][0]-j-1]for j,a in t)
-2b can be achieved by not caring about empty input
<1 or b --> <1or b to save an extra character
that'll be a SyntaxError sometime later in python's development
But not yet 😉
ok then -3b max recklessness
[int(input())for i in range(int(input()))] could be [int(input())for i in[0]*int(input())] i think
in fact doing a,b=divmod(int(input()),1000) and putting the loop into exec('code;'*int(input())) might be shorter
print([946*a+v.index(b),-54*a-1000+v.index(b)][bool(b and b[0]in'XV')])
print(-54*a-1000+v.index(b)if b and b[0]in'XV'else 946*a+v.index(b))
also
r=[(H+T+O).replace(' ','')for H in" .C.CC.CCC.CD.D.DC.DCC.DCCC.CM".split('.')for T in" .X.XX.XXX.XL.L.LX.LXX.LXXX.XC".split('.')for O in" .I.II.III.IV.V.VI.VII.VIII.IX".split('.')]
r=[H+T+O for H in".C.CC.CCC.CD.D.DC.DCC.DCCC.CM".split('.')for T in".X.XX.XXX.XL.L.LX.LXX.LXXX.XC".split('.')for O in".I.II.III.IV.V.VI.VII.VIII.IX".split('.')]
another char save would be removing b=r[b] and doing if(b:=r[b])and b[0]in'XV' etc
saving a variable to v.index(b) should save a few chars
v.index(b)v.index(b)
w=v.index(b)ww
actually doing w=v.index(b)-54*a and then doing w-1000 and w+1000*a should be better
and turning r into a walrus should save a char as well
assign 1000 to some variable
that doesn't save anything does it?
also don't use divmod()
t=1000;tt
10001000
assuming your optimizations are used
oh right yes
i don't feel right about all those repeated C/X/Is
you can remove spaces from long strings and remove .replace(' ','')
yeah that's my point there
oh, indeed 😄
there's a way to do that yeah
apparently __builtins__.__dir__().__len__() is different between location where in interpreter, it is 161 but in code, it is 158
more golf
lambda I,L: str().join([{~-1:[chr(__builtins__.__dir__().__len__().__floordiv__((__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())<<(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())<<__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__()))).__add__(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__()))).__add__(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())))],~-0b11:[chr(I) for I in [type(True).real.__class__.__init_subclass__().__sizeof__().__mul__(4).__add__(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())),0x42,0b1000011]],(~-0+0xA)//0b11:[chr(i+0b10+__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())) for i in [0o101,0x42,0b1000011]],0b100:[chr(L+6) for L in [0o101,0x42,0b1000011]],0xA//~-0b11:[chr(I+9) for I in [0o101,0x42,0b1000011]],(~-4)*(~-3):[chr(l+12) for l in [0o101,0x42,0b1000011]],0b111:[chr(l+15) for l in [0o101,0x42,0b1000011,0o104]],0o10:[chr(L+~-20) for L in [0o101,0x42,0b1000011]],(~-0b100)**2:[chr(i+ord('\x16')) for i in [0o101,0x42,0b1000011,0b1000100]]}[l[~-0b10]][~-0+l[0b10][i]-l[int()]]for i,l in enumerate([(i,I[i],[i for i in range(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__()),min(len(I),len(L)))if (I[i]!=I[i.__sub__(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__()))])|(L[i]>L[i-1]+(~-0b10)/0b10)]+[len(I)])for i in range(len(list(zip(I,L))))if (i==int())|(I[i]!=I[~-int()+i])|(L[i]>L[~-(not __name__=="__main__")+i]+(~-0b10)/0b10)])])
And now syntax highlight on desktop is not working 💀
!e
print((__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())<<(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())<<__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__()))).__add__(__builtins__.__dir__().__len__().__floordiv__(__name__.__dir__().__len__())))
And this is 0b101
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
5
i guess thats because of quit() exit() copyright() license() help() shit
Maybe
So my code probably being specific that you can only run it on a script
Not interpreter
btw, __builtins__ is module in repl and builtin dict in script
that also may cause confusion
!e print(type(builtins))
@fleet bridge :white_check_mark: Your 3.12 eval job has completed with return code 0.
<class 'module'>
hmm, maybe it is other way around
also it is not clearly documented what exactly __buultins__ is
Can you elaborate? Is what you have in mind CPython implementation specific?
How to access any variable without specify it
like?
for example for the code yesterday
how to access I, L etc.
without specify it
without exec and eval
define ,,without specify it"
globals()['L']
great, I forget this, this is helpful
without attr name appearing in code object as name
!e
x=1
print(next(filter(lambda v:isinstance(v,int),globals().values())))
@karmic pumice :white_check_mark: Your 3.12 eval job has completed with return code 0.
1
thx
!e
I = 1
print(builtins.getattr(builtins, 'globals')()[chr(((1<<3)*(0b11**2)).add(1))])
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
1
now I only need to obfuscate the string
it's also different based on whether its from __main__ or not
in __main__, __builtins__ is builtins
in other modules, __builtins__ is builtins.__dict__
Ok
not cpython specific
or at least doesn't have to be
though in practice it would be much easier to do in cpython than in other implementations
its like that, except its also a module in __main__
!e ```py
import os
print(os.builtins)
@versed eagle :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | {'__name__': 'builtins', '__doc__': "Built-in functions, types, exceptions, and other objects.\n\nThis module provides direct access to all 'built-in'\nidentifiers of Python; for example, builtins.len is\nthe full name for the built-in function len().\n\nThis module is not normally accessed explicitly by most\napplications, but can be useful in modules that provide\nobjects with the same name as a built-in value, but in\nwhich the built-in of that name is also needed.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <buil
... (truncated - too long, too many lines)
Full output: https://paste.pythondiscord.com/GWC4PMVEIHXIS72XPGFMZ4GG2Y
its very silly
in cpython you can do things like bytecode modification and tracing and hooking global name lookups and whatnot
Yeah, that's what I had in mind
but in any python implementation you can use codecs
codecs reference?
or at least, any conformant implementation
nvm, i see it
this gives you full control over what gets compiled
you could perform a translation like xy -> x, y
very cool. wasn't aware of this
what do you want this for?
xy -> x, y isn't really a common transformation
xy -> x * y or xy -> (x)(y) is more common
mostly just for fun. I want to be able to simulate multiple returns the way that it works in Go
that seems really annoying to work with
you wouldn't be able to return variables with multicharacter names
the main purpose is to make this possible:
xy = (2, 3)
(lambda x, y: x + y)((lambda: xy)()) # returns 5
That seem correct
(lambda: xy)() # -> (2,3)
(lambda: x,y)((2,3)) # -> 5
!e
def a(x,y):return x+y
print(a((2,3)))
@grave grail :x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 2, in <module>
003 | print(a((2,3)))
004 | ^^^^^^^^
005 | TypeError: a() missing 1 required positional argument: 'y'
Nvm
oh
for that you'd need both expansion and a *
just kidding
Anyone interested to build a obfuscating code generator
Basically it generate obfuscated code from integer and string
For a set complexity
!e
something = type('thing', (), {'__init__': lambda self, s: self.value = s})("yes")
type(something).__iter__ = lambda self: iter(self.value)
for c in something:
print(c)
@stark granite :x: Your 3.12 eval job has completed with return code 1.
001 | File "/home/main.py", line 1
002 | something = type('thing', (), {'__init__': lambda self, s: self.value = s})("yes")
003 | ^
004 | SyntaxError: invalid syntax
raahhhh
self.__setattr__('value', s) or setattr(self, 'value', s)
lambdas have only expressions
no statements
ah
!e
something = type('thing', (), {'__init__': lambda self, s: setattr(self, 'value', s)})("yes")
type(something).__iter__ = lambda self: iter(self.value)
for c in something:
print(c)
@stark granite :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | y
002 | e
003 | s
i cant actually believe
i recall you could mess around with globals somehow so that this code would be like valid:
# messing around with globals
hello_world(print) # prints «hello_world»
yes
you could do that
but how
!e ```py
from ctypes import py_object
import atexit, builtins
def init_missing_hook(dct, func):
ob_base_p = py_object.from_address(id(dct) + 8)
class missing_hook(dict):
slots = ()
def missing(self, key, ob_base_p=ob_base_p, builtins=builtins):
try:
ob_base_p.value = builtins.dict
return (builtins.dict | self)[key]
except KeyError:
return func(self, key)
finally:
ob_base_p.value = class
ob_base_p.value = missing_hook
@atexit.register
def unhook():
ob_base_p.value = dict
return unhook
init_missing_hook(globals(), lambda G, key: lambda func:func(key))
hello_world(print)```
@rugged sparrow :white_check_mark: Your 3.12 eval job has completed with return code 0.
hello_world
basically makes the globals dict a subclass with an overridden __missing__ dunder
I have the following functions:
def add_(x, y, z):
if x is None: return (z - y, y, z)
if y is None: return (x, z - x, z)
if z is None: return (x, y, x + y)
def sub_(x, y, z):
if x is None: return (z + y, y, z)
if y is None: return (x, x - z, z)
if z is None: return (x, y, x - y)
def mul_(x, y, z):
if x is None: return (z / y, y, z)
if y is None: return (x, z / x, z)
if z is None: return (x, y, x * y)
def div_(x, y, z):
if x is None: return (z * y, y, z)
if y is None: return (x, x / z, z)
if z is None: return (x, y, x / y)
representing equations in three variables. If two of the three arguments are numeric and one is None, a tuple containing the values of all variables will be returned. I'm trying to write a function which composes these functions in the following way:
f(g(x1, y1, None), y2, z2), producing a function which accepts 4 arguments, and providing any 3 of them returns a tuple with the correct value of all 4.
The goal is for this composition to work not just for two three-variable functions, but also for functions returned by earlier compositions which may have arbitrarily many arguments.
Here's a non-working version of what I'm trying to code up.
# this doesn't work
def comp_(f, g):
def inner(*args):
args = iter(args)
a, b, c = g(next(args), next(args), None)
_, *args = f(c, *args)
return tuple([a, b, *args])
return inner
f = add_
ff = comp_(f, f)
fff = comp_(ff, f)
ffff = comp_(fff, f)
# these all pass
assert ff(1, 2, 3, None) == ff(1, 2, None, 6) == (1, 2, 3, 6)
assert fff(1,2,3,4, None) == (1, 2, 3, 4, 10)
assert ffff(1,2,3,4,5, None) == (1, 2, 3, 4, 5, 15)
# ff(None, 2, 3, 6) < -- this throws an error
Any help is appreciated.
Omg where is this
isnt this the local function reference bug
nvm
ok i just stuck your code in a debugger and its immediately obvious where the problem is @elfin ether
you're calling g with "None, 2, and None"
Yes, that's the problem with a specific instance of calling the function, but the entire function logic is wrong. I only shared the function to give others somewhat of an idea of what I'm trying to achieve. The problem really is "what does the correct composition logic look like". The code I shared only works for a very limited set of functions; for example, g is assumed to only have three arguments. I think I need to either check the signature for the number of arguments or do something like:
from cytoolz.functoolz import curry
from itertools import chain
def comp_(f, g):
def inner(*args):
args = iter(args)
curr = curry(g)
while callable(curr):
prev = curr
arg = next(args)
curr = curr(arg)
args = chain([arg], args)
curr = prev(None)
_, *args = f(curr[-1], *args)
return tuple([*curr[:-1], *args])
return inner
oh ok
def add_(*args):
# it's assumed that you pass at least 3 things in, and only one of them is None
*o, a = args
if a is None:
return (*o, sum(o))
i = o.index(None)
o.pop(i)
o.insert(i, a - sum(o))
return tuple(o)
that accepts more arguments
I think the variadic argument in inner is part of the problem. When composing (in the way I've described) variadic functions you can't say where the args of one end and the args of the other begin. It'd be nice to somehow wrap "inner" with a signature that is "isomorphic to" the signature of g (except the last arg) + the signature of f
if your goal is for composed functions to behave as f2(f1(arg1, arg2, arg3), arg4, arg5) then you either need to use keyword args or make them take 5 args. not 4
It's somewhat more like this (though not exactly):
A(B(C(v, w, None), x, None), D(y, z, None), q)
f(f(f(1, 2, None)[-1], 3, None)[-1], f(4, 5, None)[-1], None)
or do you want your arguments to act as a window? such that py compose(f1, f2) -> function(arg1, arg2, arg3, arg4) where arg[1-3] is passed into f1 and arg[2-4] is passed into f2
the last argument of the function is meant to represent the right hand side of some equation. for the sake of the composed function, it is an "intermediate result" that we don't care about
compose(add_, add_) should act as (w + x + y = z)
ff(None, 2, 3, 6) -> f(f(None, 2, None)[-1], 3, 6)
add_, mul_, div_, sub_, are all meant to act as x @ y = z, (replacing @ with the appropriate operation) where you provide two of the variables and you get the values for all of them
@elfin ether what tuple should this return?
cause is it supposed to be (1,2,3,6)?
(if it is, you would need to walk backwards from the final result tuple, and pass its args back into the first function to pull back the 1)
actually wait that would fail anyways because f(None, 2, None) would crash
you're right, their implementation is just wrong
it seems like the goal is some sort of equation solver, where you can make an equation with one variable and then find the variables value
mhm
but once you start working with multiplication and division you start having the possiblility for multiple solutions
for (None, 2, 3, 6) it should give (None, 3, 6) to the first add and then (None, 2, 3) to the second one
(*f(None, 2, f(None, 3, 6)), 6) is the desired result
only if the operation isnt known, or if there are multiple unknown values
but they specify what operation it is, and there's only one unknown
@elfin ether if this is your goal, you're going about it in a way that will be hard to do
yea, and the functions would need to move around for (1, 2, 3, None)
the simple three additions case looks like this:
(w + x) + y = z
and we're saying "(x=2, y=3, z=6), tell me w". By passing f(None, 3, 6) to the "outer" call to f, we can obtain (w+x) = 3, which we can then feed into the inner call to f.
1, 2, 3, None is the simplest use case
getting the result is trivial, you just evaluate all the functions with the values
my point there is that figuring out how to layout the functions is nontrivial once you have enough args
wdym
comp(add_, comp(mul_, div_)) -> x1 + (x2 * (x3 / x4)) = x5
comp(comp(mul_, div_), _add) -> (x1 * (x2 / x3)) + x4 = x5
and then adding in the fact that any of those args can be None
for example, if x2 for the second example is None then the first step would need to be None + x4 = x5
then with that result (r1) you would need to do x1 * None = r1
then with that one you would need to do None / x3 = r2
so simple composition would not work, you would need to build some sort of tree of operations and then intelligently chose branches based on arguments
idk, the tree is built for us when we compose the functions
but in order to know how to apply the arguments to the tree you need to know more information about each level
(f for function, o for operand, a for answer)
for c = comp(f₁, f₂, ... fₙ), we have c(o₁, o₂, ..., oₙ, o₍ₙ₊₁₎, a) -> a = o₁ o₂ f₁ o₃ f₂ ... o₍ₙ₊₁₎ fₙ
(i used reverse polish notation here because the order of operations is unambiguous)
(and also it's a chain, not a tree, which is useful here)
if a is unknown, just evaluate the expression
if a is known, then the unknown is in the expression
if it's in the expression, you can just walk up the expression, and evaluate until you find it
then when you reach the unknown you can start from the top and reduce down to the unknown
then you're just left with the the unknown, and it's not unknown anymore
you only need a tree if you use infix notation
yes but you'd still need to walk through it
and tree walking is complicated
fair
Does this assume each f takes three arguments?
yes, though it could be generalised
as long as the user passes the correct amount of arguments for the functions, and the functions have some way to expose how many arguments they want
ok, i think i can write this
and the functions have some way to expose how many arguments they want
to get this you can look at the code objects, or just have the functions expose an attribute
i'm just going to use the curry trick i posted above
you can get the arg count from function.__code__.co_argcount (for simple functions with non-variable argcounts)
mhm
presumably, none of the functions would be variadic
or if they are, they would be the last function
slice = lambda to_slice, start=0, end=None, step=1: [(ret := [to_slice[i] for i in range(sorted((start if start >= 0 else start+len(to_slice), 0, len(to_slice)-1))[1],sorted((end if end >= 0 else end+len(to_slice), 0, len(to_slice)))[1], step)]), "".join(ret) if type(to_slice) is str else ret][1]
is the object returned by globals() the same in every module in the import chain, or different? and has this changed with python versions?
it is the global namespace of current module
it is same for every call inside one module, different in different modules
i doubt it has been changed
yeah, i did some tests, and it is different in every module. is there a way to override the globals of a calling module?
i.e., if i import package z into package y, some code in z would update the globals of y
well, this is #esoteric-python
fair enough
but basically my goal is to dynamically assign values to every undefined variable in a script, by simply importing the helper module
or not even assign, just intercept the name resolution process so i can do something with the names of the undefined variables
sys._getframe(1).f_globals should be the globals of the caller
it seems the fakeglobals is interfering with the import process now
__missing__: name=_imp
Exception ignored in: <function _get_module_lock.<locals>.cb at 0x000002330F137670>
Traceback (most recent call last):
File "<frozen importlib._bootstrap>", line 177, in cb
AttributeError: 'str' object has no attribute 'acquire_lock'
first line is my trace print, last line happens because i return the name if it is not found in locals, globals, or builtins
any idea how to make it not interfere with the import?
oh, nvm, i fixed it by setting the getframe depth to 2 instead of 1
or maybe that didnt fix anything
yeah nevermind, the issue persists
you can do nothing in these import-related frames
and you can detect them by looking at something, for example check if __name__.startswith('importlib')
not perfect, but will do the work most of the time
i messed around a bit, and im not sure how but i managed to silence most of the tracebacks
the weird thing is that i still see names like setattr and isinstance go through my __missing__ method
so i just grab their values from builtins so importlib stops complaining
now the real issue is that im still unable to modify the globals of the importing module
comparing the id's of the sys._getframe(1).f_globals in the imported module, and globals() in the importer, they are different
hm ok, through trial and error it seems that the actual importer module's globals are at frame depth 6...
i guess that's because you cant change globals object through frame object
unbelievable. it works
you can change type of global namespace with ctypes trickery
i kept the py_object.from_address(id(g) + 8).value = FakeGlobals code someone pointed to earlier
yeah
where g = sys._getframe(6).f_globals
is there a way to find the real caller's frame, without hardcoding values?
yes
depends what you mean by real caller
and how much you know about it
like, the function or module or whatever stack that is one level above my code, excluding things like importlib
e.g. to get the importing module's frame, its at depth 6 during the import process, but how can i guarantee this 6 will work every time?
the module you want is one level above your code
you can iterate over frames and skip whichever you dont like (with 'importlib' in its name for example)
maybe you can skip entire stdlib
if frame.f_globals["__name__"] in sys.stdlib_module_names or something like that
you can also inspect module filename
mhm
yup, i will try these when im polishing up the code
one question though, why am i assigning the subclass of dict directly here, instead of an instance? if im not mistaken, globals() is an instance of dict
because there you are not replacing instance, you are changing type of existing instance
it is like globals().__class__ = DictSubclass
but most types dont support changing types, so you are manually doing it by assigning new value to the pointer that stores type of globals()
all objects store their types somewhere in them
in recent versions they store it on offset 8 (so it is second pointer in their struct, first value is either refcount or __dict__, i dont remember)
yep, it's refcount stuff
__dict__ is stored variably iirc
oh wow i need to pay attention more to whats going on with python
apparently there's a new thing where the vm will manage the __dict__ for you
variably?
like not in the same place every time
i don't think that's the case
tp_dictoffset
it should be in the same place for as long as the class/instance is alive
unless i haven't studied enough
so that is what the 8 is for, makes sense
yeah its always in the same place for the same type
by variably i meant [not in the same place for every object]
ok makes sense
whereas something like ob_type is always at a specific and constant offset (in this case, 8) for every object
everything works pretty much great, thanks everyone. i'll look into iterating and filtering the frames tomorrow as its almost 7am
one more question for the record, is it possible to make python accept x y z as valid syntax (with the spaces separating names)?
yes if you modify python's source code
well, im not going that far 😁
@quartz wave :white_check_mark: Your 3.12 eval job has completed with return code 0.
5
or if you modify the source of the program
codecs
with codecs or an import hook or something
yes
it should be typeable with a keyboard
i can type that with my keyboard
:3
and not with alt codes and what not
... i can type that with my keyboard :3
use codecs then
in other words, ascii space
use codecs or an import hook
can i do that externally?
?
wdym
cause the script with the spaces is being passed directly into the interpreter
yes
all the shenanigans happen during the import of my module
sorry its 7am, im not really making much sense
it's ok
what does a pth file do, or how could i use a codec/import hook?
if you're just running it with python3 path/to/file.py, then .pth files will work fine
so will messing with site stuff
its a file that python runs before anything else
reference
its meant to be used to mess with sys.path (hence .pth) but it can run arbitrary python
oo interesting
so i can use it to replace all the space characters in a script with commas before it is executed?
maybe
or by implementing custom codec
codec is a thing that handles encodings, you can specify your own encoding in file # coding: my_stuff and register codec that can handle that
it should search file content for x y z patterns and replace them with whatever you want and return result which will be parsed by python parser
!e
print(int().str().len())
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
1
the first value is refcount, and the dict can sometimes be placed before the object in its header (which also holds things for the GC). tp_dictoffset afaik is used for the offset of the dictionary from the instance, and if it is set to -1 then python will manage the placement for you. (if it is 0 then no dict is created). When python is managing the dict for you it can sometimes be placed inside the header, or in a few other places.
it makes sense
LHS | RHS where an addtion takes place in the LHS
as opposed to ... Term1 + Term 2 where X | Y takes places in Term 1
i would like it to be parsed as a + (b | c) because bitwise ops are kinda multiplication, and should be evaluated before addition
its from C i think
It’s a logical operator still
Arithmetic operators take precedence
and and or are also logical, but they are evaluated last
exactly
it makes sense for relops and logops to be done last
and by the looks of it the binary equivalents take precendence too
bitwise ops have lower priority overall
but internally they follow sensible rules
& is like *
| is like +
^ is also like +
but apparently has higher precedence than |
bitshifts are also like *
& is like and, but instead of true and false (1 bit), it process multiple bit
| is or
^ is xor
bitshift is int(x*2**n)
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
00000011 -0000100
!e
print(f"{3:08b} {~(3 & 1 << 8):08b}")
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
00000011 -0000001
!e
print(f"{3:08b} {~(3 | (1 << 8)):08b}")
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
00000011 -100000100
I guess I have to do it with the good ol'
!e
print(f"{3:08b} {0x100 - 3:08b}")
!e
print(f"{3:08b} {0x100 - 3:08b}")
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
00000011 11111101
???
Tried to get bitwise operators to display two's complement
But ~ just prints the absolute value with a negative sign for negative integers
Um
!e
print(~-1)
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
0
I forgot binary string formatting doesn't show two's complement
Two's complement is a way of representing negative integers in binary. It also happens to play nicely with arithmetic
Instead of using the actual formula for a negative integer's two's complement, I tried to get there with bitwise operators
And for some reason with ~ too
!e
original = "10011"
length = len(original)
print(f'{abs(int(original, 2))^int("1"*length,2)+1:08b}')
🤔
!e
original = "10011"
length = len(original)
print(f'{(abs(int(original, 2))^int("1"*length,2))+1:08b}')
@grave grail :white_check_mark: Your 3.12 eval job has completed with return code 0.
00001101
!e
original = 0b10011
print(f"{0x100 - original:08b}")
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
11101101
The top three bits are apparently wrong here
Oh but I guess you could use 1 as the padding character
!e
print(f"{abs(~2):1>8b}")
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
11111111
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
11111111
!e print(~-2)
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
1
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 11111-10
002 | 111111-1
003 | 11111110
004 | 11111111
005 | 11111110
006 | 11111111
007 | 11111100
008 | 11111101
@cloud fossil :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 11111110
002 | 111111-1
003 | 11111-10
004 | 11111-11
005 | 1111-100
006 | 1111-101
007 | 1111-110
008 | 1111-111
Ye
!e ```py
pad=lambda n,k=8:''.join(f'{n>>i&1}'for i in range(k)[::-1])
for n in range(-5, +5+1):
print(f'{n:+} = {pad(n)}')
@fleet bridge :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | -5 = 11111011
002 | -4 = 11111100
003 | -3 = 11111101
004 | -2 = 11111110
005 | -1 = 11111111
006 | +0 = 00000000
007 | +1 = 00000001
008 | +2 = 00000010
009 | +3 = 00000011
010 | +4 = 00000100
011 | +5 = 00000101
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/WBJAGVVC6P2Q7QNWGTRSFVLEXQ
discord mobile moment
discord mobile syntax highlighting is Not Good™️
is this the text channel to talk about technomancy in?
what?
pretty much
!e
from einspect import impl
@impl(str)
def thing(self):
return 1
print(''.thing())
@karmic pumice :x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 5, in <module>
003 | print(''.thing())
004 | ^^^^^^^^
005 | AttributeError: 'str' object has no attribute 'thing'
@dry mirage are you busy?
o/ yeah haven't gotten around to patching that yet, wonder what the issue is
!e
from einspect import view
view(str)["xyz"] = lambda: 5
s = "a"
print(s.xyz())
@dry mirage :x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 6, in <module>
003 | print(s.xyz())
004 | ^^^^^
005 | AttributeError: 'str' object has no attribute 'xyz'
hm...
i tried to do that too hahah
i was getting some errors when some dictionaries stuff was happening
i dont have a clue on how it actually works so dont know either :(
!e
from einspect.structs import PyTypeObject
strType = PyTypeObject(str)
strType.tp_as_sequence[0].sq_concat = lambda self, other: "abc"
a = "dog"
print(a + "cat")
@dry mirage :white_check_mark: Your 3.12 eval job has completed with return code 0.
abc
struct slots still work, but 3.12 fixed the old immutable flag hack it seems
i've been messing with codecs for the past day, and got regular encode/decode to work, but for some reason the incremental decoder isnt working, and i have no idea why
def _encode(input, errors="strict") -> tuple[bytes, int]:
return utf_8.encode(_(input), errors)
def _decode(input, errors="strict") -> tuple[str, int]:
decoded, size = utf_8.decode(input, errors)
decoded = decoded.replace("_ ", "_,")
decoded = "foo"
return decoded, size
class UndersIncrementalDecoder(utf_8.IncrementalDecoder):
def decode(self, input, final=False) -> str:
self.buffer += input
if final:
buffer = self.buffer
self.buffer = b""
decoded, _ = _decode(buffer)
return decoded
return ""
def get_frame() -> inspect.FrameInfo | None:
return next(
(
frame
for frame in inspect.stack()
if frame.code_context and "# coding: _" in inspect.getsource(frame.frame).splitlines()
),
None,
)
def register_executor(frame: inspect.FrameInfo) -> None:
atexit.register(CustomGlobals.at_exit, frame.frame)
py_object.from_address(id(frame.frame.f_globals) + 8).value = CustomGlobals
@register
def search_function(encoding_name) -> CodecInfo | None:
if encoding_name == "_":
if frame_info := get_frame():
register_executor(frame_info)
return CodecInfo(
name="_",
encode=_encode,
decode=_decode,
incrementaldecoder=UndersIncrementalDecoder,
)
return None
there is no error, python just seems to default to using utf-8 no matter what i do
my goal is to modify the source code python sees before execution
the decoded = "foo" line was supposed to test that theory, but it never shows up
what is ~ in python?
bitwise inversion
do you need an incremental decoder/encoder?
!e
# test
import math as M
F=lambda N: N*(N**2-1)
P=lambda K: K*F(2+K)+(2**K)*(F(K)**2)/F(2*K)
Q=lambda K: (1/(16**K))*((4/(8*K+1))-(2/(8*K+4))-(1/(8*K+4))-(1/(8*K+6)))
print(
M.pi,
4 * M.atan(1),
355/113,
22/7,
Q(-0.001480581466888099),
P(3),
sep="\n"
)
@sly root :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 3.141592653589793
002 | 3.141592653589793
003 | 3.1415929203539825
004 | 3.142857142857143
005 | 3.141592653589792
006 | 24.942857142857143
You can also get it from 2 * math.acos(0) or 2 * math.asin(1)
noice
And don't forget math.radians(180)
i find it funny that you can get E with (1+2e-17)**(2**52)
2**52 casually sitting here
and oops wrong channel
from math import atan
atan(1) + atan(2) + atan(3) # pi
Doesn't work on my machine, 1 + 2e-17 evaluates to 1.0 (probably because 2e-17 is such a small number so it doesn't even try to calculate this)
floating point math moment
something isn't right here. it should be (1+1/n)**n for large n, e.g. (1+1e-10)**1e10
!e ```py
print(
(1j**1e-9).imag*2e9,
)
@fleet bridge :white_check_mark: Your 3.12 eval job has completed with return code 0.
3.141592653589793
@sly root :x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 5, in <module>
003 | E=C**P
004 | ~^^~
005 | OverflowError: (34, 'Numerical result out of range')
!e ```py
import math as M
print(1+2e-16, 252)
print(
(1+2e-16)(2**52),
M.e,
sep="\n"
)```
@sly root :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1.0000000000000002 4503599627370496
002 | 2.718281828459045
003 | 2.718281828459045
ah, interesting indeed. 1/2**52 is actually 2.22e-16, not 2e-16, but the error gets cut off by the float precision limits.
how to change the return type of print()?
hook it
yeh but which method?
!e ```py
import sys
print = lambda x, y: x + y
sys.stdout.write(str(print(3, 5)))
sys.stdout.write(str(print('a', 'b')))
@fleet bridge :white_check_mark: Your 3.12 eval job has completed with return code 0.
8ab
import sys
from fishhook import hook
@hook.cls(print.__class__)
class __NewPrint:
def __call__(*args, sep=' ', end='\n', file=sys.stdout):
output = sep.join(map(str, args)) + end
file.write(output)
return output
a = print('a')
print(a)
a
None
<built-in method __enter__ of _thread.lock object at 0x000002AEC3F22000>
<built-in method __exit__ of _thread.lock object at 0x000002AEC3F22000> None None None
<built-in method __enter__ of _thread.lock object at 0x000002AEC3F22000>
<built-in method __exit__ of _thread.lock object at 0x000002AEC3F22000> None None None
why?
that hooks __call__ for all <class 'builtin_function_or_method'>
A
makes sense
<built-in function print> a
<built-in function print> <built-in function print> a
```lol
there are lots of ways to hook things
Although you can pretty much do anything with the Python programming language, source code manipulation and metaprogramming isn’t really a thing. In this article we are going to look at how we can make preprocess python source files and add our extensions to the language’s syntax.
using python 3.8. if needed i can switch to a newer version
nvm, got it to work after some painful debugging
is there a way to parse code into an ast without checking if it is valid?
nope
i ended up solving my issue with a regex, but it has the side effect of not understanding the code context and interpreting symbols in strings as any other symbols
there's the tokenize module to tokenize python code
but i guess regex can be used too
hmm, maybe that would work as well
nevertheless, my abomination is almost complete
the only issue i have now is putting a .pth file in site-packages consistently
it works in a venv, but the path is wrong when installing in user-specific site
guys help me how do i fix this? I already have pygame downloaded
can you run py -0 in the terminal?
lemme chack
You meant to ask this question in #editors-ides most likely
i can't
i'm new on the server
👍 then this channel will seldom be helpful to you
why not?
Did you install Python from python.org?
yes
Did you tick the box which adds the py launcher in the installation process?
i'm using vs code
no
i started python a few days ago
type in cmd in that terminal, then run the command again
i didn't
Rerun the installer and check that box and go through the process again
so do i have to uninstall python?
I think you don't have to
ok but i use python extesion in vs code
The py launcher is independent of the editor
not the actual python
If you're using the extension and it sets up the configuration file correctly, there's no need for the py launcher
You just have to run the project with the extension
There's like a ▶️ button at the top or something if the extension is enabled
hold on
it's not green anymore
it's green again
this is the warning
nvm i'll finfish the code and see if it works
every few weeks
That checkbox is for a different configuration
Also what I posted was a screenshot from python.org, I didn't install Python like that don't worry
lmao
Did the size of opcodes in the bytecode change somewhere in 3.11? I'm seeing some weird stuff in both generating and parsing bytecode that seems to suggest some opcodes are now 4 bytes maybe?
well they're the normal 2 bytes
but with CACHEs
following them
and it's necessary to know exactly how many bytes to skip after an opcode because the CACHE is literally only for storing info
The co_code for a 26-instruction method is 118 bytes
that means that it doesn't always stay a CACHE
Hmm, but then why doesn't dis show the CACHE ops if it does support showing them?
needs show_caches=True
What do I pass to _unpack_opargs to include them?
And equally importantly, do jumps count CACHEs as size 0 or size 2
Because I'm trying to do bytecode replacement but I'm seeing weird behavior from my bytestrings for some unclear reason
2 probably
since it'd be easier to make it work that way
Yeah so apparently if you remove all CACHE instructions from co_code, it completely alters the behaviour and output from dis
Because my generated co_code is identical to the original co_code pretty much
Alright I think I've got it
I just had to measure the difference in index to detect CACHEs
In next versions I'll remove them and add them again during serialization but for now I guess the user has to add them manually
CACHE is important
the spec says they’re required, if they’re not present, the interpreter wont know if it should skip the next n bytes or read them
gotcha
the interpreter wont know if it should ...
im pretty sure it just skips them
i know
it expects them to be there
yes
i was just making a point that it cant know if cache exists or not
wdym
has anyone found any interesting esoteric usages of the new 3.12 generics
def fun[T: restriction](a: T, b: T) -> T:
return a + b
I haven't read the changes in 3.12 but WTH does that do (ik type hinting)
from what i understand, it lets you define typevars inline without the use of TypeVar
Golfing: https://www.codewars.com/kumite/6534637c5396a5f1b9d193c6?sel=6537510a49d3ef7767de1717
this is the best I managed to get:
Greeting=lambda n,rank='',formal=0:f"He{['y','llo'][a:=formal]},{f' {b}'if(b:=rank)*a else''} {n}{'!.'[a]}"
do you need the long parameter names
oh they do ugh
cool
i managed to find a shorter one
oh damn
i found another
I got to use pyasm at work today because upstream package has a bug and the PR has been open for over a week :)
nice
Greeting=lambda n,rank='',formal=0:f"He{['y','llo'][a:=formal]},{f' {rank}'*a} {n}{'!.'[a]}"
that doesn't work when rank is empty
oh wow mom i made it
i was the one who did the first “golfed” iteration of that
print "hello world"
0x3c50?
yes
cool
i have the latest
Greeting=lambda n,rank='',formal=0:f"He{['y','llo'][f:=formal]},{rank*f and' '+rank} "+n+'!.'[f]
oh
i don't get it which button do i have to press?
nvm i fixed it
!e I just made this seems kinda neat to me (it stores the state inside the TypeVar)
def _[__:lambda _=[]:_.append(_)or _](____:__):print(___:=len(__.__bound__()))or ___<____ and _(____)
_(5)
@meager zinc :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1
002 | 2
003 | 3
004 | 4
005 | 5
!e this is a similar concept but extended for a different result
def _[__:lambda _=[]:_.append(_)or _]():print(end=chr(___:=len(__.__bound__()))*(-~___%0x69<=1))or ___<0x80 and _()
_()
@meager zinc :white_check_mark: Your 3.12 eval job has completed with return code 0.
hi
What kind of sorcery syntax is this?
Python 3.12 stuff?
How are you doing def _[…]
python 3.12 stuff
they changed the type annotation syntax
they didn't change old one, they added additional syntax
yeah its new type annotation syntax:
def function[T: restriction](a: T, b: T) -> T:
return a + b
def function[T](a: T) -> T:
return a
Python Enhancement Proposals (PEPs)
I still dont understand typevars and their purpose
it's supposed to help connect the types of different arguments and the type of the return
So its sort of like an any but links argument and return type?
Whats the point of [T:str] instead of just str then?
I think there’s a difference in how subclasses/superclasses are handled
E.g. if T is a subclass of str then all cases of T must be that subclass
whereas just using str would allow them to be different
^
consider an example like
def f[T: Animal](a: T) -> list[T]:
return [a]
def g(a: Animal) -> list[Animal]:
return [a]
f(Cat()).append(Dog()) # bad, can't add a dog to list[Cat]
g(Cat()).append(Dog()) # good, can add a dog to list[Animal]
addition is a type of change
(the second call to f is supposed to be g I think) [fixed]
true
So the main purpose of type vars is dealing with inheritence?
Nice example
do you like... donuts?
while ('o_' in dir()) or (A := (0)
) or (B := 0) or print((
"\x1b[2J")) or not ((sin := ((
__import__('math'))).sin)) or not (
cos := __import__('math').cos) or (o_ := (
True)): [pr() for b in [[(func(), b) for ((z
)) in [[0 for _ in range(1760)]] for b in [[ (
"\n") if ii % 80 == 79 else " " for ii in range(
1760)]] for o, D, N in [(o, D, N) for j in range((
0), 628, 7) for i in range(0, 628, 2) for (c, d, e,(
f), g, l, m, n) in [(sin( i / 100), cos(j / 100),(
sin(A)), sin(j / 100), cos(A), cos(i / 100) ,
cos(B), sin(B))] for (h) in [d + 2] for (
D, t) in [ (1 / ( c * h * e + f * g + (5
)), c * h * g - f * e)] for (x, y) in [
(int( 40 + 30 * D * ( l * h * m - t * n)),
int( 12 + 15 * D * ( l * h * n + t * (m))))]
for (o, N) in [(x + 80 * y,int(8 * (( f * e - c
* d * g) * m - c * d * e - f * g - l * d * n)))] if
0 < x < 80 and 22 > y > 0] if D > z[o] for func in
[lambda: (z.pop((o))), lambda: z.insert((o), (D)
),(lambda: (b.pop( o))), lambda: b.insert((o),
".,-~:;=!*#$@"[ N if N > 0 else 0])]][ 0][1]
] for pr in [lambda: print("\x1b[H"),
lambda: print("".join(b))] if (A :=
A + 0.02) and ( B := B + 0.02)]
#..--~~EvanZhouDev:~~--.#
#...,2023,...#
Run this bad boy 
you stole that from that video
There is literally the programmer's name on the donut, so he gets the credit.
not me lol
whoops
I didn't mean steal
I meant like its from
My repo: https://github.com/EvanZhouDev/donut-py
Andy Sloane's Blog: https://www.a1k0n.net/
DonutPy by Julius Šyvis: https://github.com/Julius-Syvis
this video
Impressive, very nice
Lets see paul allens script
on a 1 to 10 cursed scale where would you put a holonomic_turtle subclass ?
Ok, I think this works:
def add_(x, y, z):
if x is None: return (z - y, y, z)
if y is None: return (x, z - x, z)
if z is None: return (x, y, x + y)
def comp_(*fs):
def inner(*args):
curr = None
ret = [*args]
if args[-1] == None:
for f in fs:
n = getattr(f, '__argcount__', f.__code__.co_argcount) - 2 + int(not bool(curr))
curr = f(curr[-1], *args[:n], None) if curr else f(*args[:n], None)
args = args[n:]
ret[-1] = curr[-1]
return tuple(ret)
gs = iter(fs)
index = 0
g = None
curr = None
seen_stop = False
for f in gs:
n = getattr(f, '__argcount__', f.__code__.co_argcount) - 2 + int(not bool(curr))
if None in args[:n]:
g_args = list(args[:n+1 - int(not bool(curr))])
j = args.index(None)
args = args[n:]
index += j
lhs = curr
g = f
break
index += n
curr = f(curr[-1], *args[:n], None) if curr else f(*args[:n], None)
args = args[n:]
gs = iter([*gs][::-1])
curr = None
for f in gs:
n = getattr(f, '__argcount__', f.__code__.co_argcount) - 2 + int(not bool(curr))
curr = f(None, *args[-n:], curr[0]) if curr else f(None, *args[-n:])
args = args[:-n]
if lhs:
if curr:
g_args[j] = lhs[-1]
ret[index] = g(g_args[0], None, curr[0])[j+1]
else:
ret[index] = g(lhs[-1], *g_args)[j+1]
else:
ret[index] = g(*g_args, curr[0])[j]
return tuple(ret)
n = 2
for f in fs:
n += (f.__code__.co_argcount - 2)
inner.__argcount__ = n
return inner
these all pass at least..
f = comp_(add_, add_)
g = comp_(f, f)
answer = (1, 10, 100, 1000, 10000, 11111)
assert g(1, 10, 100, 1000, 10000, None) == answer
assert g(1, 10, 100, 1000, None, 11111) == answer
assert g(1, 10, 100, None, 10000, 11111) == answer
assert g(1, 10, None, 1000, 10000, 11111) == answer
assert g(1, None, 100, 1000, 10000, 11111) == answer
assert g(None, 10, 100, 1000, 10000, 11111) == answer
You're breaking a rule which you've agreed to follow
in a python package's setup.py, is there a way to find out which exact site-packages path it is being installed to?
decided to ask here since theres no packaging channel, and this ties into the esoteric stuff i've been working on
my end goal here is to put a .pth file into a site-packages where it will be executed by the interpreter regardless of how the package was installed
from pathlib import Path
import pip
site_pkgs = Path(pip.__file__).parent.parent
not the best idea in the world, but we are in #esoteric-python
are site packages always installed in .../lib/site-packages/ ?
i made funny working interpreter for programming language in python
make number integer ask (comments are in brackets)
make count 0
make count add count 1 (increment)
zap 10 if modulo count 3 (zap just teleports to a line)
zap 8 if modulo count 5 (conditions can only be used in zap lol)
say "FizzBuzz"
zap 14
say "Fizz"
zap 14
zap 13 if modulo count 5
say "Buzz"
zap 14
say count
zap 3 if count less number (loop till end)
its called portal and completely functionless classless for and while loopless
only has ints and strings for now but im happy
Only works if the pip you're installing with is contained in the same site-packages you're installing to, right?
yes
if you know at least one package that is installed in site-packages, you can do that (replace pip with that module in my example)
so basically asm with more features
i can get the user site packages and global site packages with site.getusersitepackages() and site.getsitepackages(), but how do i know which one to copy the pth file to during installation?
i dont know whats asm, just got this idea and decided to do it
assembly
with more features
but no fucntion
s
loool
btw guys how could i do this shorter?
while 1:w=[int(input())for _ in' '*8];print(w.index(max(w)))
while w:=eval('int(input()),'*8):print(w.index(max(w)))
thanks dude
def fib(N):
f = [0, 1]
for i in range(1, N+1):
f.append(f[i-2] + f[i-1])
return f[N]
def fib(N):
f=[0,1]
for i in range(1,N+1):
f.append(f[i-2]+f[i-1])
return f[N]
def fib(N):
f=[0,1]
for i in range(N):
f.append(f[i]+f[i+1])
return f[N]
def fib(N):
f=[0,1]
for i in range(N):f.append(f[i]+f[i+1])
return f[N]
def fib(N):
f=[0,1]
for i in range(N):f+=[f[i]+f[i+1])
return f[N]
Could this be shortened any further?
fib=lambda n:n<2and n or f(n-1)+f(n-2)
Yeah that
!e
import fishhook
fishhook.hook(str, name="__index__")(lambda x:["zero", "one", "two", "three", "four"].index(x))
print(range(0, 100, 3)["three"])
@restive void :white_check_mark: Your 3.12 eval job has completed with return code 0.
9
!e
import fishhook
fishhook.hook(int, name="__repr__")(lambda x:dict(zip(range(5), ["zero", "one", "two", "three", "four"])).get(x, fishhook.orig(x)))
print(*range(10))
@fleet bridge :white_check_mark: Your 3.12 eval job has completed with return code 0.
zero one two three four 5 6 7 8 9
hehe
depends if you want the package to be user-specific or not
Just a nitpick, you are recursively calling a function that doesn't exist
i think the user or pip decides that, for example based on whether the user ran the installation command as admin or not
!e ```py
from fishhook import*
hook(int,name="repr")(lambda x:o if(o:=orig(x))and x>9999 else''.join(["zero","one","two","three","four","five","six","seven","eight","nine"][int(v)]+["","ty"," hundred"," thousand"][~-len(orig(x))-i]+" "for i,v in enumerate(o)))
print(~-1)
print(9261)
print(4 + 890)
@meager zinc :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | zero
002 | nine thousand two hundred sixty one
003 | eight hundred ninety four
if you have it recurse you can get it to 999999 but I was lazy
!e (also it doesn't handle teens very well and doesn't handle tens very well)
from fishhook import*
hook(int,name="__repr__")(lambda x:o if(o:=orig(x))and x>9999 else''.join(["zero","one","two","three","four","five","six","seven","eight","nine"][int(v)]+["","ty"," hundred"," thousand"][~-len(orig(x))-i]+" "for i,v in enumerate(o)))
print(11, 12, 13, 14, 15, 16, 17, 18, 19)
for i in "123456789":
print(int(i * 4))
@meager zinc :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | onety one onety two onety three onety four onety five onety six onety seven onety eight onety nine
002 | one thousand one hundred onety one
003 | two thousand two hundred twoty two
004 | three thousand three hundred threety three
005 | four thousand four hundred fourty four
006 | five thousand five hundred fivety five
007 | six thousand six hundred sixty six
008 | seven thousand seven hundred seventy seven
009 | eight thousand eight hundred eightty eight
010 | nine thousand nine hundred ninety nine
onety one onety two onety three onety four onety five onety six onety seven onety eight onety nine
i love that ❤️
wait
they all are like that
😄
not a nitpick, I missed that, good point
f=fib=lambda n:n<2and n or f(n-1)+f(n-2)
tbh, this naming system is better than actual one
Someone in a recent reform wanted to spell machine as masheen
eengleesh moomeent
1840 is pretty recent
eengleesh
compared to several hundred thousand years yeah
is there a way to detect if my package is being installed in the user site packages or system site packages? i have a .pth file that is included as a data file, with the path Lib/site-packages. it works fine when installed in a venv or system site-packages, where the path matches, but in the user site-packages the path should be PythonXX/site-packages instead. if the pth file is placed in the user site-packages under Lib/site-packages it does not work
or maybe the better question is, is there a way to determine the exact path to the site-packages of installation, so that i don't have to handle all the cases separately going off just sysconfig.get_path("purelib")
i can get either the system site-packages or the user site-packages, but i cant determine which to copy my file to during installation, as the user could install into either
I hate the walrus.
From datetime.py in the standard library, original:
s = _format_time(self._hour, self._minute, self._second, self._microsecond, timespec)
tz = self._tzstr()
if tz:
s += tz
return s
supposed improvement:
s = _format_time(self._hour, self._minute, self._second, self._microsecond, timespec)
if tz := self._tzstr():
s += tz
return s
My suggestion:
return \
(
_format_time(self._hour, self._minute, self._second, self._microsecond, timespec)
+
(("", tz)[tz] for tz in (self._tzstr(),))[0]
)
anyway, here is the result of my hard work and wasted time lol
https://github.com/lemonyte/_
Most of it comes from experience, the more you golf the better you get
and along the way you'll learn the useful tricks
is there a shorter way of saying None in python?
like in less than 4 chars
or a solution that would allow an if to be put against it
can you show code?
0?
what is the usecase
the empty string is technically 0 characters
The exercise is just to return None, I have a solution that doesn't return anything so implicitly returns None but I was wondering if there's a way to return None if ... But then change None into something that allows if to be stacked against it
# 1:
return a if c else None
# 2:
if c:return a
