Perl Guru
-
-
I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
There's something literally called The International Obfuscated C Code Contest
-
There's something literally called The International Obfuscated C Code Contest
I prefer the Underhanded C Contest, where the goal is to write a subtle bug that can be exploited maliciously but is plausibly deniable as a mistake if discovered.
-
@hungrier I'm aware of that one, it's just that its purpose is to serve as a cautionary tale.
-
@wft "caution, don't use C or stuff like this may happen to you by 'accident'"
-
@hungrier I'm aware of that one, it's just that its purpose is to serve as a cautionary tale.
I don't know if that's the intention but I always thought of it as a showcase for exactly this sort of thing, so you'd have a place for it and ideally keep it out of your actual work.
#include <math.h> #include <sys/time.h> #include <X11/Xlib.h> #include <X11/keysym.h> double L ,o ,P ,_=dt,T,Z,D=1,d, s[999],E,h= 8,I, J,K,w[999],M,m,O ,n[999],j=33e-3,i= 1E3,r,t, u,v ,W,S= 74.5,l=221,X=7.26, a,B,A=32.2,c, F,H; int N,q, C, y,p,U; Window z; char f[52] ; GC k; main(){ Display*e= XOpenDisplay( 0); z=RootWindow(e,0); for (XSetForeground(e,k=XCreateGC (e,z,0,0),BlackPixel(e,0)) ; scanf("%lf%lf%lf",y +n,w+y, y+s)+1; y ++); XSelectInput(e,z= XCreateSimpleWindow(e,z,0,0,400,400, 0,0,WhitePixel(e,0) ),KeyPressMask); for(XMapWindow(e,z); ; T=sin(O)){ struct timeval G={ 0,dt*1e6} ; K= cos(j); N=1e4; M+= H*_; Z=D*K; F+=_*P; r=E*K; W=cos( O); m=K*W; H=K*T; O+=D*_*F/ K+d/K*E*_; B= sin(j); a=B*T*D-E*W; XClearWindow(e,z); t=T*E+ D*B*W; j+=d*_*D-_*F*E; P=W*E*B-T*D; for (o+=(I=D*W+E *T*B,E*d/K *B+v+B/K*F*D)*_; p<y; ){ T=p[s]+i; E=c-p[w]; D=n[p]-L; K=D*m-B*T-H*E; if(p [n]+w[ p]+p[s ]== 0|K <fabs(W=T*r-I*E +D*P) |fabs(D=t *D+Z *T-a *E)> K)N=1e4; else{ q=W/K *4E2+2e2; C= 2E2+4e2/ K *D; N-1E4&& XDrawLine(e ,z,k,N ,U,q,C); N=q; U=C; } ++p; } L+=_* (X*t +P*M+m*l); T=X*X+ l*l+M *M; XDrawString(e,z,k ,20,380,f,17); D=v/l*15; i+=(B *l-M*r -X*Z)*_; for(; XPending(e); u *=CS!=N){ XEvent z; XNextEvent(e ,&z); ++*((N=XLookupKeysym (&z.xkey,0))-IT? N-LT? UP-N?& E:& J:& u: &h); --*( DN -N? N-DT ?N== RT?&u: & W:&h:&J ); } m=15*F/l; c+=(I=M/ l,l*H +I*M+a*X)*_; H =A*r+v*X-F*l+( E=.1+X*4.9/l,t =T*m/32-I*T/24 )/S; K=F*M+( h* 1e4/l-(T+ E*5*T*E)/3e2 )/S-X*d-B*A; a=2.63 /l*d; X+=( d*l-T/S *(.19*E +a *.64+J/1e3 )-M* v +A* Z)*_; l += K *_; W=d; sprintf(f, "%5d %3d" "%7d",p =l /1.7,(C=9E3+ O*57.3)%0550,(int)i); d+=T*(.45-14/l* X-a*130-J* .14)*_/125e2+F*_*v; P=(T*(47 *I-m* 52+E*94 *D-t*.38+u*.21*E) /1e2+W* 179*v)/2312; select(p=0,0,0,0,&G); v-=( W*F-T*(.63*m-I*.086+m*E*19-D*25-.11*u )/107e2)*_; D=cos(o); E=sin(o); } }
-
I hope it can be used on Windows without installation.
Why does it matter?
-
I hope it can be used on Windows without installation.
Why does it matter?
Locked down environment.
-
@Gąska I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
while(*p++=*q++);
The entire reason why
=
and++
even return a value at all is to enable code like this.Worse yet, the only use for that is in
strcpy
et al., which are library functions anyway. And only exist in that form because C strings are retarded to begin with.But at least I presume back then it was for performance reasons, unlike anything Perl, e.g. maybe the compiler produced faster code for this than for the the logical equivalent (for whatever reason) or, god forbid, the smaller source code size actually mattered.
-
I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
There's something literally called The International Obfuscated C Code Contest
This only shows that you can write Perl in any language.
-
I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
There's something literally called The International Obfuscated C Code Contest
This only shows that you can write Perl in any language.
Python?
-
I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
There's something literally called The International Obfuscated C Code Contest
@hungrier I'm aware of that one, it's just that its purpose is to serve as a cautionary tale.
Not cautionary enough.
Guess who has won the IOCCC twice? Larry Wall.
Perl is no coincidence, just proof that Larry is still waiting for his lifetime achievement award.
-
@JBert Hah! Called it!
-
-
I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
There's something literally called The International Obfuscated C Code Contest
I once got the core logic of an othello game from there... (the UI was a command line so he could fit the source into 1K)
-
I hope it can be used on Windows without installation.
You need Eclipse and Python to use PyDev, which is hardly surprising as it is an Eclipse extension for Python development. It works well with virtual environments, and with analysis tools like pylint. My only real complaints about it are that a few of the key bindings are quite idiosyncratic by Eclipse norms, at least on macOS. I know it works on Windows; one of my cow-orkers uses that combination.
-
@Gąska I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
while(*p++=*q++);
The entire reason why
=
and++
even return a value at all is to enable code like this.Worse yet, the only use for that is in
strcpy
et al., which are library functions anyway. And only exist in that form because C strings are retarded to begin with.This particular construct - yes. But there are many more scenarios where you can save a couple keystrokes by using the return value of assignment. Especially when handling linked lists - and C programmers love linked lists.
But at least I presume back then it was for performance reasons
That was their excuse, yes. All the way up to early 2000s.
-
@Gąska and linked lists are almost as bad as C strings.
-
-
The one redeeming feature of strings in C is how anyone who uses them is promptly dissuaded from any form of string typing.
-
-
and linked lists are almost as bad as C strings.
Why?
You learn and use them for their Big O performance, but usually their terrible locality gives worse performance than a dense array in practice.
There's uses for linked lists, but you're almost certainly better off with astd::vector<int>
or maybe astd::deque<int>
than astd::list<int>
.
-
@Gąska I don't remember that there was this urge in C programmers to do cute tricks so their programs look more interesting.
while(*p++=*q++);
The entire reason why
=
and++
even return a value at all is to enable code like this.- That code is asking for a buffer overflow attack
- Please tell me at least when you're implementing your own string code it is more interesting than just a bad
strcpy()
clone.
-
That code is asking for a buffer overflow attack
Depends on what else is going on… but yes,
strcpy()
is dangerous that way.OTOH, C strings are way better than the contemporaneous Pascal counted strings, which used a single byte to hold the string length. 255
charactersbytes is enough for anyone!
-
@dkf I've got nothing against C strings but when copying one you have to pay attention to your target buffer size. Since you're probably not tracking your source string length separately, that should be checked in that loop:
while(--n)*p++=*q++;*p=0;
-
while(--n && *q)*p++=*q++;*p=0;
FTFY, at least that way your code won't cause an access violation (or leak someone else's memory) as long as the input string is correctly null-terminated. It still may if the input string isn't terminated; I don't see any way to protect against that with c strings.
-
@ixvedeusi And that's why you don't write code like that in 5 minutes.
-
@ixvedeusi And that's why you don't write code like that in 5 minutes.
Yeah, every expert can write that in 5 seconds!
Spending more than that time makes them second-guess themselves and start writing buggy code.
-
@_P_ I am an expert, and I do, but then it looks like
our_string_copy_macro(buffer, source)
.
-
OTOH, C strings are way better than the contemporaneous Pascal counted strings, which used a single byte to hold the string length. 255
charactersbytes is enough for anyone!The only problem with Pascal strings is that the counter is only 1 byte. All modern languages use pointer-sized length counter, which has two major benefits: the length (in bytes) is always known which allows efficient preallocation, and making substrings - one of the most common string operations - doesn't require copying.
-
OTOH, C strings are way better than the contemporaneous Pascal counted strings, which used a single byte to hold the string length. 255
charactersbytes is enough for anyone!At the time, given the hardware constraints they had... it pretty much was!
The modern version, which uses either 4 bytes or a native-int of bytes, is pretty much the best possible way to go that we've found so far.
-
and making substrings - one of the most common string operations - doesn't require copying
Huh? That's pretty cool, but... what language supports that? All the implementations I'm familiar with, the size int comes immediately before the buffer, so substrings do require copies.
-
@Mason_Wheeler said in Perl Guru:
and making substrings - one of the most common string operations - doesn't require copying
Huh? That's pretty cool, but... what language supports that?
D, Go, Swift, C++17 (via string_view), and of course, the best language of all. Exact implementation details vary, but they all share the same idea - they store the length in each substring separately. Java uses Pascal-style strings too, and it used to do copy-less substrings, but doesn't do that anymore to make better use of interning.
-
std::list<int>
But now you're talking about a particular implementation.
Is the locality of a linked list implemented using 2 (or 3 for doubly linked) arrays really that bad?
-
std::list<int>
But now you're talking about a particular
implementationdata structure.FTFY.
Is the locality of a linked list implemented using 2 (or 3 for doubly linked) arrays really that bad?
It's not a linked list anymore then.
-
@dfdub I'm not quite sure I understand what you mean, but your "average" implementation doesn't put nodes in a contiguous region. That's the problem.
Usually you got something like:
struct Node; struct Node { int payload; struct Node *next; };
and every Node gets
new'dmalloc'd individually. Of course you can improve on that with pool allocators, flat lists, or whatever.
-
It's not a linked list anymore then.
Wait, what? How is it not a linked list anymore just because I'm using array offsets, i.e. pointers to a contiguous memory region, instead of naively using pointers to random memory? The concept is the same.
-
every Node gets malloc'd individually
Yeah, but that's a naive implementation if you know what the list will contain and that locality is important.
-
It's not a linked list anymore then.
Wait, what? How is it not a linked list anymore just because I'm using array offsets, i.e. pointers to a contiguous memory region, instead of naively using pointers to random memory? The concept is the same.
It's not the same. Linked list is a data structure. It's defined by memory schema and algorithms. It has very specific performance characteristics that are direct consequences of that memory schema and those algorithms. If you change the memory schema, you get different data structure with different algorithms and different performance characteristics - a completely different data structure.
If we were talking about data types you would be correct (because data type is defined by its values and operations). But we're talking about data structures. Please don't confuse the two.
-
@Gąska
You're going to die on that hill, aren't you? In that case, I'm just going to point out that your own source disagrees with you: https://en.wikipedia.org/wiki/Linked_list#Linked_lists_using_arrays_of_nodes
-
@dfdub oh, you mean that. I thought you meant a chain of resizable arrays or something, since you were talking about having multiple arrays (and what you linked here can be implemented using exactly 1 array).
-
and what you linked here can be implemented using exactly 1 array
The way it's usually taught in university, you use 2 or 3 separate arrays for data, next index and (optionally) previous index.
-
and what you linked here can be implemented using exactly 1 array
The way it's usually taught in university, you use 2 or 3 separate arrays for data, next index and (optionally) previous index.
I thought parallel arrays were a well-known anti-pattern, whose answer is always "use an array of records instead"...
-
@Medinoc I do believe while array-of-structs is more readable to a human, struct-of-arrays is better for performance because it vectorizes better.
-
@error I'm a bit disappointed this hasn't updated since 2015. But at the same time, impressed that it was still active in 2015.
-
All modern languages use pointer-sized length counter
A lot of them use two counters: one for the length of the contents, and another for the length of the buffer holding the contents. Keeping those separate allows you to make appending to the string enormously faster…
-
struct-of-arrays is better for performance
Especially so in Java if you can use arrays of primitives.
-
and what you linked here can be implemented using exactly 1 array
The way it's usually taught in university, you use 2 or 3 separate arrays for data, next index and (optionally) previous index.
Honestly, that's the first I ever heard of this. Probably a consequence of living and studying in a different country.
@Medinoc I do believe while array-of-structs is more readable to a human, struct-of-arrays is better for performance because it vectorizes better.
Depends on access patterns. If your use case is such that it makes sense at all to store the next index instead of traversing the collection sequentially, then it's basically guaranteed that storing it inline will yield better performance than separate index array. But in general, SoA indeed can improve performance by more efficient cache use.
-
-
@Gąska I've got data that shows that it is outright faster than C++ for some tasks.