00:00 < bridge> in contrast to rust which already has it and you just use it 00:00 < bridge> programming vs coding 00:01 < bridge> ah 00:01 < bridge> i disagree 00:01 < bridge> plz disagree in greater detail :) 00:02 < bridge> ```c 00:02 < bridge> // Compare function for qsort 00:02 < bridge> int cmpfunc(const void* a, const void* b) 00:02 < bridge> { 00:02 < bridge> return (*(int*)a - *(int*)b); 00:02 < bridge> } 00:02 < bridge> 00:02 < bridge> // Function to return K'th smallest 00:02 < bridge> // element in a given array 00:02 < bridge> int kthSmallest(int arr[], int N, int K) 00:02 < bridge> { 00:02 < bridge> // Sort the given array 00:02 < bridge> qsort(arr, N, sizeof(int), cmpfunc); 00:02 < bridge> 00:02 < bridge> // Return k'th element in the sorted array 00:02 < bridge> return arr[K - 1]; 00:02 < bridge> } 00:02 < bridge> ``` 00:02 < bridge> see 00:02 < bridge> is this programming 00:02 < bridge> a quick google and copy 00:02 < bridge> its no different 00:02 < bridge> u just complain about having more functions available in std 00:02 < bridge> but u can do the same with C 00:02 < bridge> its why i find this argument pointless 00:04 < bridge> but its because u focus "programming" or "engineeriing" to simple algorithm exercises 00:04 < bridge> engineering is how you architect applications in whole 00:04 < bridge> etc 00:04 < bridge> was this (that `k_smallest` is using) true btw? 00:04 < bridge> no 00:04 < bridge> well 00:04 < bridge> idk 00:04 < bridge> > Note: This is functionally-equivalent to self.sorted().take(k) but much more efficient. 00:04 < bridge> xD 00:04 < bridge> its just that 00:04 < bridge> sort and take the k element 00:05 < bridge> doesnt sound related 00:05 < bridge> hmm 00:05 < bridge> [4,3,6,1] -> k = 3 -> [1,3,4] 00:06 < bridge> I mean how the sorting works 00:06 < bridge> the algorithm 00:07 < bridge> ```rust 00:07 < bridge> pub(crate) fn k_smallest>(mut iter: I, k: usize) -> BinaryHeap { 00:07 < bridge> if k == 0 { 00:07 < bridge> return BinaryHeap::new(); 00:07 < bridge> } 00:07 < bridge> 00:07 < bridge> let mut heap = iter.by_ref().take(k).collect::>(); 00:07 < bridge> 00:07 < bridge> iter.for_each(|i| { 00:07 < bridge> debug_assert_eq!(heap.len(), k); 00:07 < bridge> // Equivalent to heap.push(min(i, heap.pop())) but more efficient. 00:07 < bridge> // This should be done with a single `.peek_mut().unwrap()` but 00:07 < bridge> // `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior. 00:07 < bridge> if *heap.peek().unwrap() > i { 00:07 < bridge> *heap.peek_mut().unwrap() = i; 00:07 < bridge> } 00:07 < bridge> }); 00:07 < bridge> 00:07 < bridge> heap 00:07 < bridge> } 00:07 < bridge> ``` 00:07 < bridge> this is itertools version 00:07 < bridge> idk if its same as std 00:07 < bridge> ah std returns a iterator 00:07 < bridge> not a binary heap 00:08 < bridge> btw how did you find it? (asking bcs I was also looking for `crate::k_smallest::k_smallest(self, k)`) 00:08 < bridge> ah wait 00:08 < bridge> u linked to itertools 00:08 < bridge> u are using a library in the first place! 00:08 < bridge> ikr! 00:08 < bridge> I am not against using libs 00:08 < bridge> so ur comparision is already completly wrong 00:09 < bridge> u also have libs in C 00:09 < bridge> for common algos 00:09 < bridge> biased 00:09 < bridge> xD 00:09 < bridge> https://github.com/rust-itertools/itertools/blob/c116c200f97b39d521285e93e06f00ce9093bf40/src/k_smallest.rs#L4 00:10 < bridge> i go sleep 00:10 < bridge> gn 00:10 < bridge> gn and ty 00:18 < bridge> the ABI requires you to AFAIK 00:20 < bridge> IMO it's nice that you can use good algorithms without implementing everything yourselves 00:20 < bridge> even C has qsort 😉 00:21 < bridge> yeah but I went researching about sorting an array of fixed length and I found about this 00:34 < bridge> I did some leetcode today, I'm soooo out of practice 😦 00:35 < bridge> :O leetcode sounds fun 00:36 < bridge> btw Learath have you heard about this before? 00:38 < bridge> I've heard about it before, however I'm not sure how relevant they are in practice 00:47 < bridge> Wot you doing? 00:47 < bridge> What even are you scanning? 00:54 < bridge> hmm it appears that `qsort` uses `quicksort` which in worst-case performance is `O(n^2)` while `Bitonic sort` worst-case is `O(log^2(n))`. 00:57 < bridge> xD I completely missed these two last msgs from chiller I read `BOT` and thought it was github :kek: 01:02 < bridge> :c 01:17 < bridge> bitonic sort cannot be implemented on (current) CPUs though 01:17 < bridge> so it's not really useful for C ^^ 01:17 < bridge> :O true 01:27 < bridge> not always 01:30 < bridge> glibc qsort will try mergesort first, musl uses heapsort, msvc uses quicksort 01:31 < bridge> ah ty I was looking for this info 😉 01:31 < bridge> glibc also might be falling back to insertion sort when it gets small enough, though I don't remember 01:32 < bridge> ic, well then this is nullified xD 01:32 < bridge> https://elixir.bootlin.com/glibc/latest/source/stdlib/qsort.c yeah if it resorts to quicksort, it'll only partially quicksort and finish it off with insertion sort 01:33 < bridge> Only in context of hardware 01:33 < bridge> ok ty :) 01:36 < bridge> Funnily enough as far as the standard is concerned qsort doesn't even have any requirements, it could be quantum bogo sort 01:39 < bridge> I guess that this makes standard-compliance practically easier than having to prove performance requirements for compliance -- zogtib 01:41 < bridge> Sometimes requirements can become an issue, like the requirements on `unordered_map` in C++ permanently crippling it. So maybe the C approach of leaving it up to the implementers was the better choice 01:51 < bridge> I guess that performace behaviour is something important but it can make standard-compliance maybe harder than necessary because programmers don't care only for things required by the standards anyways. 01:52 < bridge> *because programmers depend on implementations also for things the standards doesn't include etc 01:57 < bridge> Thus, including things like that in standards would make doings things correctly harder because of the compliance overhead, even if those are practically necessary in implementations anyways. (I think this is want I mean) 01:57 < bridge> Thus, including things like that in standards would make doings things correctly harder because of the compliance overhead, even if those are practically necessary in implementations anyways. (I think this is what I mean) 02:11 < bridge> what's this 02:46 < bridge> I just found out that desmos has `tone()` funcion 😮 08:31 < bridge> The server automatically does that bcs of spoofed atks 08:33 < bridge> This. You can reinvent the wheel million times. But for stuff that doesn't exist anyway you are forced to engineer, no way around it 08:46 < bridge> morning :poggers2: 08:47 < bridge> Good morning 08:53 < bridge> gm :) 08:54 < bridge> xD it's been 6 hours since this 09:37 < bridge> Still don’t get it. Is someone spoofing a ip and pinging you with master traffic which your server then responds to? The reflection attack? What’s the target of the attack? Did your Hoster Complain? 09:49 < bridge> Well that's the question. If the hoster also complains for master servers, then rip 09:50 < bridge> Let's wait until the attacker reads this chat and tries out😬 10:20 < bridge> lot of places say the abi in linux is parameters in `rdi, rsi, rdx, rcx, r8, and r9.` but i found for syscalls rcx is replaced by r10 10:21 < bridge> why are all cheat sheets using at&t omg 10:29 < bridge> > Functions preserve the registers rbx, rsp, rbp, r12, r13, r14, and r15; while rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11 are scratch registers. The return value is stored in the rax register, or if it is a 128-bit value, then the higher 64-bits go in rdx. Optionally, functions push rbp such that the caller-return-rip is 8 bytes above it, and set rbp to the address of the saved rbp. This allows iterating through the existing stack frames. This can 10:29 < bridge> @heinrich5991 this is from the osdev wiki 10:45 < bridge> gn 12:55 < ws-client> @Jupstar ✪ do you think it is a targeted attack to you? Or are all servers abused for one bundled reflection attack? 13:00 < bridge> The target is teeworlds ofc 13:00 < bridge> Not me 13:01 < bridge> If it would be me personally. I'd demand a wild Western like fight to settle this once and for all 13:48 < ws-client> lmao 13:49 < ws-client> Ah you assume the target is the master server it self 13:49 < ws-client> Which servers do you even host? Some alive fng 0.7 servers? 13:59 < bridge> Why arent there more emotes 13:59 < bridge> Like a hammer or hook emote 13:59 < bridge> Hf emote 14:00 < bridge> because teeworlds didnt have hammerflying intended 14:01 < bridge> Who cares about that 14:16 < bridge> Not the target, but kind of the source 14:16 < bridge> The fake source 14:16 < bridge> For the reflection 14:48 < bridge> do u guys knows how much players a vps can handle per core/ghz 14:59 < bridge> i broke hammer welp 14:59 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1176522307611676743/Base_Profile_2023.11.12_-_02.43.58.04.DVR_3.mp4?ex=656f2cc8&is=655cb7c8&hm=5cd7d1adbffa47ee3336ae175f5a0ce36fb584bf739637b441b61e47023978ec& 14:59 < bridge> but really, where can i fix it? 15:07 < bridge> 128p per shittiest vps u can buy 15:46 < bridge> 😂:brownbear: 15:51 < bridge> and after i updated my client 15:51 < bridge> https://i.imgur.com/D49GEZn.png 15:51 < bridge> gg 15:52 < bridge> Provide src and we can help you :troll: 15:52 < bridge> faie 15:52 < bridge> fair 15:52 < bridge> https://github.com/StormAxs/StA 15:53 < bridge> oh lol didn't actually think it was open source 15:53 < bridge> https://media.discordapp.net/attachments/1091796670951456809/1116992248970747945/62.gif 15:54 < bridge> XDD how long did you not merge master? 15:56 < bridge> i just synced fork 15:56 < bridge> i just synced the fork 15:56 < bridge> do u use vulkan? 15:56 < bridge> i tryed all render metods 15:56 < bridge> even open gl 106 15:57 < bridge> rip 15:57 < bridge> U see far into the future 15:57 < bridge> I'd say you have a missing data directory entry 15:57 < bridge> Do a clean rebuild 16:03 < bridge> @jupeyy_keks helped as always 16:03 < bridge> thanks jupi 16:03 < bridge> :happy_cry_cat: 16:05 < bridge> well 16:06 < bridge> where can i find hammer position while spectating? 16:06 < bridge> still this goofy bug 16:25 < bridge> @jupeyy_keks do u think player count scales log or linear 16:25 < bridge> perf wise 16:28 < bridge> ??? 16:28 < bridge> Uncorrelated 16:28 < bridge> @learath2 ok i had a brain fart 16:28 < bridge> i meant perf per player count 16:29 < bridge> hmm like if u get a beefy vps 16:29 < bridge> Okay that makes more sense 😄 16:30 < bridge> Theoretically it should exhibit polynomial behaviour with all the n^2 algorithms we use 16:31 < bridge> But that's assuming one gameserver with player count going to infinity 😄 16:36 < bridge> xd 16:36 < bridge> at work they doing a backend game server with elixir and i think something in rust 16:36 < bridge> on a 24 core machine they could handle 600 players 16:37 < bridge> which idk if its a lot 16:37 < bridge> but well completly unrelated game 16:37 < bridge> i think its 3d too 16:37 < bridge> Uff that's really bad 16:37 < bridge> i thought so too 16:37 < bridge> xd 16:37 < bridge> Is the game so complex? 16:37 < bridge> i doubt 16:37 < bridge> im not in the team 16:37 < bridge> i dont do elixir 16:38 < bridge> But network can quickly become a limiting factor 16:38 < bridge> i think its mainly cuz elixir ngl 16:38 < bridge> true 16:38 < bridge> i think they use websockets tho 16:38 < bridge> they considering quic 16:38 < bridge> I assume these 600 players are on different lobbies too? 16:39 < bridge> ye 16:39 < bridge> lobbies of 10 players iirc 16:39 < bridge> I c 16:39 < bridge> 2.9ghz 16:39 < bridge> 256gb ram 16:39 < bridge> but itjust uses 2gb iirc 16:39 < bridge> xd 16:39 < bridge> XD 16:40 < bridge> gotta have backup kek 16:44 < bridge> @learath2 when use quad trees or bsp on ddnet 16:46 < bridge> maybe in @Zwelf's rust impl of ddnet physics 😉 16:46 < bridge> it's probably easier there 17:43 < bridge> Oh yea had the same. I think something with the mapres changed. Make sure your user wide storage location matches the source code generated data folders and so on. So just running a make install in your repo should fix it 17:47 < bridge> Or updating ddnet via the package manager 18:47 < bridge> https://paste.pr0.tips/Hnw?c if anyone has a couple minutes, I'm curious how you would do this task 18:48 < bridge> where is the task? 18:48 < bridge> You just merge two sorted linked lists 18:48 < bridge> list.append(list2) 18:48 < bridge> The resulting list must also be sorted 😄 18:49 < bridge> then i'd use a datatype that is called sortedlist xd 18:49 < bridge> ok 18:49 < bridge> is that yours or from someone else? 18:49 < bridge> That's mine 18:51 < bridge> seems trivialish but also interesting, lemme try 🙂 18:51 < bridge> It's absolutely trivial, just curious how other people would go about it, there are lots of ways to do it 18:51 < bridge> ```c 18:51 < bridge> struct ListNode *mergeTwoLists(struct ListNode *list1, struct ListNode *list2) { 18:51 < bridge> struct ListNode dummy; // Dummy head node. 18:51 < bridge> struct ListNode *cur = &dummy; 18:51 < bridge> 18:51 < bridge> // While there are elements in either list. 18:51 < bridge> while (list1 && list2) { 18:51 < bridge> if (list1->val < list2->val) { 18:51 < bridge> cur->next = list1; 18:51 < bridge> list1 = list1->next; 18:52 < bridge> } else { 18:52 < bridge> cur->next = list2; 18:52 < bridge> list2 = list2->next; 18:52 < bridge> } 18:52 < bridge> cur = cur->next; 18:52 < bridge> } 18:52 < bridge> 18:52 < bridge> // Append the remaining elements of `list1` or `list2`. 18:52 < bridge> cur->next = list1 ? list1 : list2; 18:52 < bridge> 18:52 < bridge> return dummy.next; 18:52 < bridge> } 18:52 < bridge> ``` 18:52 < bridge> hello chatgpt 18:52 < bridge> hi 18:52 < bridge> nice one 18:52 < bridge> ChatGPT definitely ruined the world 18:53 < bridge> yea, I think I like that one better 18:53 < bridge> It's the same as my first one 😄 18:53 < bridge> Well same idea 18:53 < bridge> I was going to complain that yours does unnecessary writes 18:53 < bridge> inner cycle got removed 18:54 < bridge> also I find your first solution/chatgpt's solution easier to understand 18:54 < bridge> +1 18:54 < bridge> Yeah, I think I like that one better too 18:54 < bridge> ```c 18:54 < bridge> struct ListNode *mergeTwoLists(struct ListNode *list1, struct ListNode *list2) { 18:54 < bridge> if (!list1) return list2; 18:54 < bridge> if (!list2) return list1; 18:54 < bridge> 18:54 < bridge> if (list1->val < list2->val) { 18:54 < bridge> list1->next = mergeTwoLists(list1->next, list2); 18:54 < bridge> return list1; 18:54 < bridge> } else { 18:54 < bridge> list2->next = mergeTwoLists(list1, list2->next); 18:54 < bridge> return list2; 18:55 < bridge> } 18:55 < bridge> } 18:55 < bridge> ``` 18:55 < bridge> xd 18:55 < bridge> no 18:55 < bridge> https://tenor.com/view/discordmemes-gif-25118502 18:55 < bridge> noo 18:55 < bridge> NOOO 18:55 < bridge> Meh, chatgpt definitely ruined the fun of these kinds of challanges 18:56 < bridge> I got zogpt 18:56 < bridge> aka I just ask zogtib 18:56 < bridge> I was curious how you'd solve it, not how a machine learning model trained on stackoverflow where this question has been asked 10000 times would solve it 18:56 < bridge> the problem is, u didnt ask me if u want the fastest, or the cleanst, or the shortest 18:57 < bridge> fastest: don't use linked lists 18:57 < bridge> hm, are you golfing on so? 18:57 < bridge> I have a feeling you'd just ask chatgpt either way 18:57 < bridge> i think there's no gpt answers 18:57 < bridge> i mean i've done such coding challenges so often already 18:58 < bridge> I'm just doing some leetcode to warm back up to coding 18:58 < bridge> Which solution you'd pick on your own volition given nothing but the challange is what's curious to me 18:58 < bridge> @learath2 ok, here's is one i 100% did myself 18:58 < bridge> 18:58 < bridge> https://www.codewars.com/kata/52774a314c2333f0a7000688 18:59 < bridge> || 18:59 < bridge> ```c 18:59 < bridge> #include 18:59 < bridge> 18:59 < bridge> bool validParentheses(const char *s) { 18:59 < bridge> int CurP = 1; 18:59 < bridge> while(*s) { 18:59 < bridge> switch(*s++) { 18:59 < bridge> case '(': CurP *= 2; break; 18:59 < bridge> case ')': CurP /= 2; break; 18:59 < bridge> } 18:59 < bridge> } 18:59 < bridge> return CurP == 1; 18:59 < bridge> } 18:59 < bridge> ``` 18:59 < bridge> || 18:59 < bridge> my solution: 18:59 < bridge> || 18:59 < bridge> ```c 18:59 < bridge> #include 18:59 < bridge> 18:59 < bridge> bool validParentheses(const char *s) { 18:59 < bridge> int CurP = 1; 18:59 < bridge> while(*s) { 18:59 < bridge> switch(*s++) { 18:59 < bridge> case '(': CurP *= 2; break; 18:59 < bridge> case ')': CurP /= 2; break; 19:00 < bridge> } 19:00 < bridge> } 19:00 < bridge> return CurP == 1; 19:00 < bridge> } 19:00 < bridge> ``` 19:00 < bridge> || 19:00 < bridge> Ah I did this one yesterday too 19:00 < bridge> Oh, actually a different one nvm 19:00 < bridge> See now that's cute 19:00 < bridge> give me the codewars next time, then it's more fun, bcs it can compile etc. 19:01 < bridge> Hm, never tried codewars, let me give that a go too 19:02 < bridge> 🤓 `CurP <<= 1;` `CurP >>= 1;` 19:02 < bridge> Oh actually I did try codewars a bit apparently 19:02 < bridge> ```c 19:02 < bridge> struct list { 19:02 < bridge> int val; 19:02 < bridge> struct list *next; 19:02 < bridge> }; 19:02 < bridge> 19:02 < bridge> struct list *merge_inplace(struct list *a, struct list *b) { 19:02 < bridge> struct list *result; 19:02 < bridge> struct list **cur = &result; 19:02 < bridge> 19:02 < bridge> while(a && b) { 19:02 < bridge> if(a->val < b->val) { 19:02 < bridge> *cur = a; 19:02 < bridge> cur = &cur->next; 19:02 < bridge> a = a->next; 19:03 < bridge> } else { 19:03 < bridge> *cur = b; 19:03 < bridge> cur = &cur->next; 19:03 < bridge> b = b->next; 19:03 < bridge> } 19:03 < bridge> } 19:03 < bridge> 19:03 < bridge> if(a) { 19:03 < bridge> *cur = a; 19:03 < bridge> } else { 19:03 < bridge> *cur = b; 19:03 < bridge> } 19:03 < bridge> return result; 19:03 < bridge> } 19:03 < bridge> ``` 19:03 < bridge> here's mine, untested 19:03 < bridge> it has also never seen a compiler 19:04 < bridge> As a fan of the double pointer trick I approve, the dummy head in gpts answer was ugly 19:04 < bridge> yea, I also didn't like it so much 19:05 < bridge> it's essentially a hidden double pointer with a useless value field 19:06 < bridge> You are missing some *s I think 19:06 < bridge> yes 19:06 < bridge> Atleast my mental compiler isn't liking the amount of -> and & there per datatype 😄 19:06 < bridge> compiler says I should use `&(*cur)->next` instead of `&cur->next` 19:06 < bridge> not necessary in rust :p 19:07 < bridge> Yeah I think I would change the very last if block to a ternary and have this as my final answer 19:24 < bridge> ```rs 19:24 < bridge> use std::mem; 19:24 < bridge> 19:24 < bridge> struct List { 19:24 < bridge> val: i32, 19:24 < bridge> next: Option>, 19:24 < bridge> } 19:24 < bridge> 19:24 < bridge> fn merge_inplace(mut a: Option>, mut b: Option>) -> Option> { 19:24 < bridge> let mut result = None; 19:24 < bridge> let mut cur: &mut Option> = &mut result; 19:24 < bridge> 19:24 < bridge> loop { 19:24 < bridge> match (a, b) { 19:24 < bridge> (Some(mut a_inner), Some(mut b_inner)) => { 19:24 < bridge> if a_inner.val < b_inner.val { 19:24 < bridge> let a_next = mem::replace(&mut a_inner.next, None); 19:24 < bridge> cur = &mut cur.insert(a_inner).next; 19:24 < bridge> a = a_next; 19:24 < bridge> b = Some(b_inner); 19:24 < bridge> } else { 19:24 < bridge> let b_next = mem::replace(&mut b_inner.next, None); 19:24 < bridge> cur = &mut cur.insert(b_inner).next; 19:24 < bridge> a = Some(a_inner); 19:24 < bridge> b = b_next; 19:24 < bridge> } 19:24 < bridge> } 19:24 < bridge> (Some(a_inner), None) => { 19:24 < bridge> *cur = Some(a_inner); 19:24 < bridge> break; 19:24 < bridge> } 19:24 < bridge> wow, that took a while 19:25 < bridge> can chatgpt do this? I'd be impressed 😮 19:25 < bridge> took me ~15min 19:25 < bridge> this time developed together with the compiler 19:25 < bridge> @learath2 ^ 19:25 < bridge> ```rust 19:25 < bridge> use std::mem; 19:25 < bridge> 19:25 < bridge> // Definition for singly-linked list. 19:25 < bridge> #[derive(PartialEq, Eq, Clone, Debug)] 19:25 < bridge> pub struct ListNode { 19:25 < bridge> pub val: i32, 19:25 < bridge> pub next: Option>, 19:25 < bridge> } 19:25 < bridge> 19:25 < bridge> impl ListNode { 19:25 < bridge> #[inline] 19:25 < bridge> fn new(val: i32) -> Self { 19:25 < bridge> ListNode { next: None, val } 19:25 < bridge> } 19:25 < bridge> } 19:25 < bridge> 19:25 < bridge> pub fn merge_two_lists( 19:25 < bridge> list1: Option>, 19:25 < bridge> list2: Option>, 19:25 < bridge> ) -> Option> { 19:25 < bridge> // Using a dummy head to simplify edge cases 19:25 < bridge> let mut dummy = Box::new(ListNode::new(0)); 19:26 < bridge> let mut cur = &mut dummy; 19:26 < bridge> 19:26 < bridge> // Two mutable references to list1 and list2 19:26 < bridge> let mut l1 = list1; 19:26 < bridge> let mut l2 = list2; 19:26 < bridge> 19:26 < bridge> while l1.is_some() && l2.is_some() { 19:26 < bridge> let next_node = if l1.as_ref().unwrap().val < l2.as_ref().unwrap().val { 19:26 < bridge> NOT CHECKED 19:26 < bridge> just copy pasted 19:26 < bridge> rip chiller 19:26 < bridge> not bad, compiles 19:26 < bridge> It's impressive that it can write rust at all given it's training set doesn't include quite as much of it 19:26 < bridge> it's writing rust like C though 19:26 < bridge> it is pretty bad in it tbh 19:27 < bridge> Yeah, it just wrote whatever one would write in C in Rust 😄 19:27 < bridge> <_voxeldoesart> arent strusts just objects LOL 19:27 < bridge> but color me impressed 19:27 < bridge> but now that it can serch the internet it's sometimes useful to find crates, bcs it reads the docs and at least kind of understands it 😄 19:27 < bridge> hmm. what was the prompts, @jupeyy_keks? 19:27 < bridge> *s++ would increment the value not the pointer no? 19:28 < bridge> Does rust have some guarantee as to the order match branches will be checked? 19:28 < bridge> rewrite in rust 19:28 < bridge> top to bottom 19:28 < bridge> or does ++ have more priority than derefrence 19:28 < bridge> `*s++` increments the pointer 19:28 < bridge> ++ sticks harder 19:28 < bridge> ah ok 19:28 < bridge> good to knwo 19:28 < bridge> good to know 19:28 < bridge> everything is evaluated in order it's written 19:29 < bridge> also applies to function arguments, etc. 19:29 < bridge> Hm, that sounds bad for performance, the compiler isn't allowed to reorder stuff? 19:29 < bridge> no, unless it can prove it doesn't affect the outcome 19:30 < bridge> Oh, okay 19:30 < bridge> I think C++ does the same nowadays? 19:30 < bridge> I thought even if it could prove it doesn't matter it wasn't allowed to change the order 19:30 < bridge> why *= and /= instead of just += and -= xdd 19:30 < bridge> C and C++ both use the same as-if rule, as long as there is no observable change it's fine 19:30 < bridge> that actually serves a value there 😉 19:31 < bridge> same for rust 19:31 < bridge> but in C, order was undefined at some point, I thought 19:31 < bridge> and C++ 19:31 < bridge> what value xd 19:31 < bridge> 1 / 2 * 2 = 0 19:32 < bridge> 1 / 2 * 2 = 0 ≠ 1 19:32 < bridge> ah 19:32 < bridge> that makes sense 19:32 < bridge> 0 - 1 + 1 = 0 = 0 19:32 < bridge> nice 19:34 < bridge> what if there are more than 64 parenthesis? 19:34 < bridge> If there are no sequence points order is undefined. If there are sequence points the compiler is only allowed to reorder if it can prove that it changes nothing 19:35 < bridge> *31 19:35 < bridge> If no sequence points the compiler can do whatever anyway 19:35 < bridge> I don't think Rust has the idea of sequence points though, atleast I haven't encountered it yet 19:41 < bridge> then your computer explodes 19:42 < bridge> gcc -Dint=__int128 19:43 < bridge> 😏 19:49 < bridge> Did any of you know about the Boyer-Moore string search algorithm? 19:50 < bridge> After doing an exercise implementing strstr I was curious what a less naive solution looks like and came across it 19:50 < bridge> looks weird xd 19:51 < bridge> one thing i dislike about c++, this is confusing, but it makes some code look "nice" or "smart" 19:52 < bridge> It makes code look sexy asf and you know it 19:52 < bridge> @learath2 it makes it look smart as i said 19:52 < bridge> but not always writing "smart" code is good 19:52 < bridge> specially if its not for a code golf 19:53 < bridge> anyway rn im a nasm guy not rust guy 19:53 < bridge> :poggers2: 19:54 < bridge> @learath2 i found a snippet of asm to calc next power of 2 19:54 < bridge> and its rly nice 19:54 < bridge> ```c 19:54 < bridge> void a () { 19:54 < bridge> int c = 0; 19:54 < bridge> ++++++++++++++c; 19:54 < bridge> } 19:54 < bridge> ``` 19:54 < bridge> 19:54 < bridge> how do you like this code? 19:54 < bridge> xd 19:54 < bridge> https://github.com/edg-l/aoc2023-nasm 19:54 < bridge> oh look yet another snippet no one would ever see anywhere but in IOCCC 19:55 < bridge> ```x86asm 19:55 < bridge> next_pow_2: 19:55 < bridge> dec eax 19:55 < bridge> bsr rcx, rax 19:55 < bridge> inc ecx 19:55 < bridge> mov eax, 1 19:55 < bridge> shl rax, cl 19:55 < bridge> ret 19:55 < bridge> ``` 19:55 < bridge> @learath2 can u generate this with C 19:55 < bridge> Oh wait, is AOC now? 19:55 < bridge> no its in december 19:55 < bridge> Yes, I think I even sent a blog post about it sometime 😄 19:55 < bridge> @learath2 this snippet uses eax and rax 19:55 < bridge> so my understanding is 19:56 < bridge> using eax builds to a instruction that is smaller 19:56 < bridge> than rax? 19:56 < bridge> and thats why its better? 19:56 < bridge> or using rax will result in same perf 19:56 < bridge> smaller instructions = better cache 19:56 < bridge> that's a question for @chairn 19:57 < bridge> It should in theory, but who knows, maybe it ends up pipelining worse and performs worse with 131 of them in a row 19:57 < bridge> Modern CPUs are a mystery 19:57 < bridge> (it's taken me a while (I have some "minor" health difficulties)) 19:57 < bridge> ```c 19:57 < bridge> struct listnode { 19:57 < bridge> int val; 19:57 < bridge> struct listnode *next; 19:57 < bridge> } 19:57 < bridge> 19:57 < bridge> struct listnode * 19:57 < bridge> mergeTwoLists(struct listnode *a, struct listnode *b) 19:57 < bridge> { 19:57 < bridge> struct listnode **p[2] = { &a, &b }; 19:57 < bridge> struct listnode *n, *lh; 19:57 < bridge> int i; 19:58 < bridge> 19:58 < bridge> if (!a) return b; 19:58 < bridge> if (!b) return a; 19:58 < bridge> lh = a->val < b->val ? a : b; /* list head */ 19:58 < bridge> 19:58 < bridge> n = lh; 19:58 < bridge> while (1) { 19:58 < bridge> i = a->val < b->val; 19:58 < bridge> n = n->next = *p[i]; 19:58 < bridge> if (!(*p = (*p)->next)) { 19:58 < bridge> n->next = *p[i ^ 1]; 19:58 < bridge> break; 19:58 < bridge> } 19:58 < bridge> } 19:58 < bridge> 19:58 < bridge> return lh; 19:58 < bridge> } 19:58 < bridge> ``` 19:58 < bridge> i found out there is a mov instruction that can be used for branchless programming 19:58 < bridge> Ah yep, it's also iirc turing complete on it's own 😄 19:58 < bridge> CMOVL 19:58 < bridge> COVIDL 19:58 < bridge> https://www.felixcloutier.com/x86/cmovcc 19:58 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1176597629879193622/image.png?ex=656f72ef&is=655cfdef&hm=d37b772c767985d40a90dfd29029ca680e49fdbc6be7585f54cc2f4414bc86c2& 19:58 < bridge> there is lot of variants 19:59 < bridge> @ryozuki if u want the real fun, do the opposite: reverse engineerig 19:59 < bridge> too hard, i gotta start with mastering assembly first 19:59 < bridge> conditional moves are so hard to program with, I learned assembly on things that don't have them 20:00 < bridge> You also don't think in terms of conditional moves when programming in C either, so it's not easy from that direction either 20:00 < bridge> but thats the dope thing about asm 20:00 < bridge> fine grained control 20:00 < bridge> u cant get more control 20:00 < bridge> if ur a master of asm u are a magician 20:00 < bridge> At that point, I found it's just more rope to hang yourself with, atleast on modern cpus 😦 20:01 < bridge> https://www.reddit.com/r/teeworlds/s/pSAOHT7Liu 20:01 < bridge> I wish it was possible for mere humans like me to properly understand and program assembly for cpus that span a decade and are complicated beyond belief 20:01 < bridge> well im off, im taking a bike to some place and walk a mountain with a friend 20:01 < bridge> Woahh 20:01 < bridge> kek 20:01 < bridge> cya later 20:01 < bridge> don't, it's too late, bears will eat you 20:01 < bridge> xdd 20:01 < bridge> its rly relaxing to do this 20:01 < bridge> u see the whole city of barcelona 20:01 < bridge> with their lights 20:01 < bridge> from the mountain 20:02 < bridge> a good stress relief from work 20:02 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1176598559265673267/IMG_20231029_193348.jpg?ex=656f73cc&is=655cfecc&hm=2ddedbc744a8386650c07a549649fbeb4cb0116b1af25d1295beb86ecdf2ffdb& 20:02 < bridge> took this some time ago 20:02 < bridge> and my camera is shot 20:02 < bridge> shit 20:02 < bridge> mobile 20:02 < bridge> That is a nice picture 20:03 < bridge> ye 20:09 < bridge> This is incorrect actually, this could be OK but it's definitely less wrong. 20:10 < bridge> ```c 20:10 < bridge> struct listnode * 20:10 < bridge> mergeTwoLists(struct listnode *a, struct listnode *b) 20:10 < bridge> { 20:10 < bridge> struct listnode **p[2] = { &a, &b }; 20:10 < bridge> struct listnode *n, ln; 20:10 < bridge> int i; 20:10 < bridge> 20:10 < bridge> if (!a) return b; 20:10 < bridge> if (!b) return a; 20:10 < bridge> 20:10 < bridge> n = &ln; 20:10 < bridge> while (1) { 20:10 < bridge> i = a->val < b->val; 20:10 < bridge> n = n->next = *p[i]; 20:10 < bridge> if (!(*p = (*p)->next)) { 20:10 < bridge> n->next = *p[i ^ 1]; 20:10 < bridge> break; 20:10 < bridge> } 20:10 < bridge> } 20:10 < bridge> 20:10 < bridge> return lh.next; 20:10 < bridge> }``` 20:14 < bridge> That's also wrong. This compiles though (last submission): 20:14 < bridge> ```c 20:14 < bridge> struct listnode * 20:14 < bridge> mergeTwoLists(struct listnode *a, struct listnode *b) 20:14 < bridge> { 20:14 < bridge> struct listnode **p[2] = { &a, &b }; 20:14 < bridge> struct listnode *n, ln; 20:14 < bridge> int i; 20:14 < bridge> 20:14 < bridge> if (!a) return b; 20:14 < bridge> if (!b) return a; 20:14 < bridge> 20:14 < bridge> n = &ln; 20:14 < bridge> while (1) { 20:14 < bridge> i = a->val < b->val; 20:14 < bridge> n = n->next = *p[i]; 20:14 < bridge> if (!(*p[i] = (*p[i])->next)) { 20:15 < bridge> n->next = *p[i ^ 1]; 20:15 < bridge> break; 20:15 < bridge> } 20:15 < bridge> } 20:15 < bridge> 20:15 < bridge> return ln.next; 20:15 < bridge> }``` 20:16 < bridge> what if more than 128 parenthesis ? 20:16 < bridge> ryozuki can give you the llvm code to allow any amount of bits 20:16 < bridge> xd 20:16 < bridge> i want your solution with recursive call 20:19 < bridge> If I wanted to sell it I'd prob say that it checks if `a` or `b` is `NULL` only they get changed and not on every iteration. 🙂 20:21 < bridge> in general yes, but there can be alignment issues or different uops generated leading to overall less performance. But that's intel's fault though 20:32 < bridge> <_voxeldoesart> @furo321 ancient idea but lol 20:32 < bridge> With a single type of paren you can just use a single bit to keep track of it, no? 20:34 < bridge> Mh, not enough, just a single int should be enough for `2^sizeof (int)` pairs tho 20:37 < bridge> Open paren is always legal s++, close paren legal iff s > 0 s--, if you end with anything but s == 0 invalid, otherwise valid 20:41 < bridge> Yeah, that also how I solved recursively, but the same works in a loop: 20:41 < bridge> ```cpp 20:41 < bridge> bool ValidParenthesesImpl(const char *pStr, unsigned Num) 20:41 < bridge> { 20:41 < bridge> switch(pStr[0]) 20:41 < bridge> { 20:41 < bridge> case '(': return ValidParenthesesImpl(pStr + 1, Num + 1); 20:41 < bridge> case ')': return Num > 0 && ValidParenthesesImpl(pStr + 1, Num - 1); 20:41 < bridge> case '\0': return Num == 0; 20:41 < bridge> default: return ValidParenthesesImpl(pStr + 1, Num); 20:41 < bridge> } 20:42 < bridge> } 20:42 < bridge> 20:42 < bridge> bool ValidParentheses(const char *pStr) 20:42 < bridge> { 20:42 < bridge> return ValidParenthesesImpl(pStr, 0); 20:42 < bridge> } 20:42 < bridge> ``` 20:52 < bridge> Why did your mind go directly to recursive? The problem doesn't intuitively look recursive to me 20:53 < bridge> I only went specifically for recursive because Chairn asked 20:53 < bridge> Ah, I see 20:54 < bridge> I really need to make peace with recursion. Whenever I feel like doing recursion for a problem I'll use an explicit stack instead 21:04 < bridge> yes, default substring search algorithm AFAIK 21:04 < bridge> Atleast for glibc yeah 21:05 < bridge> glibc is my goto for seeing what is better than naive 21:08 < bridge> interesting. I think I like the earlier solutions better, due to clarity. this one might minimize branches though 21:10 < bridge> that's usually the better idea, no stack smashing due to untrusted inpt 21:10 < bridge> that's usually the better idea, no stack smashing due to untrusted input 21:30 < bridge> ```c 21:30 < bridge> struct ListNode *mergeTwoLists(struct ListNode *list1, struct ListNode *list2) { 21:31 < bridge> struct ListNode *head = (struct ListNode *)&list1; 21:31 < bridge> struct ListNode **tail = &head; 21:31 < bridge> 21:31 < bridge> while (list1 && list2) { 21:31 < bridge> struct ListNode **min = list1->val < list2->val ? &list1 : &list2; 21:31 < bridge> *tail = *min; 21:31 < bridge> *min = (*min)->next; 21:31 < bridge> tail = &((*tail)->next); 21:31 < bridge> } 21:31 < bridge> 21:31 < bridge> *tail = (struct ListNode *)((uintptr_t)list1 | (uintptr_t)list2); 21:31 < bridge> return head->next; 21:31 < bridge> } 21:31 < bridge> ``` 21:31 < bridge> GPeakT 21:31 < bridge> the line before the return is cool xd 21:31 < bridge> it might also break clang 21:53 < bridge> it might break more than clang as it's implementation defined behaviour 22:26 < bridge> ah right nullptr doesn't need to be 0 22:32 < bridge> hmmm. but in clang/gcc on common targets, this is defined to be all-0-bit-pattern, no? 22:32 < bridge> where is the impl defined behavior 22:33 < bridge> `((uintptr_t)list1 | (uintptr_t)list2)` 22:34 < bridge> `nullptr` isn't guaranteed to translate to `0` if it is cast to some integer type 22:35 < bridge> oh i see 22:36 < bridge> seems annoying to have to list1 ? list1 : 0 lol 22:36 < bridge> darn 22:43 < bridge> i got a problem while using TAB to fill commands `/top5` for example 22:43 < bridge> but get the game crash, the question is: where can i find `NumCommands` probably this is where i missed 22:43 < bridge> https://cdn.discordapp.com/attachments/293493549758939136/1176639113215086662/image.png?ex=656f9991&is=655d2491&hm=ad302e74557b0b5c6fae8d903e4d17c30390dd35828b2a88471b536102aaf8d4& 22:44 < bridge> does this happen in ddnet 22:44 < bridge> own client 22:44 < bridge> or means gameMode? 22:47 < bridge> btw i still have this hammer issue 22:50 < bridge> that's a divide by zero error 22:50 < bridge> % implicitly divides to find the remainder