Code Puzzle Thread

Discuss Autohotkey related topics here. Not a place to share code.
Forum rules
Discuss Autohotkey related topics here. Not a place to share code.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Code Puzzle Thread

07 Dec 2017, 15:27

Thanks for incentive!
Don't know if this is allowed, but it certainly doesn't break given rules and yields desired result!

Code: Select all

	for , l in List
		x:="abcd " l

Code: Select all

	for k in List
		x:="abcd " k
P.s.: I got it already before, but I didn't think to this concatenation: "abcd "
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Code Puzzle Thread

07 Dec 2017, 16:37

O.k., maybe I cheated (came in through not secured back door).
If so, let's go non plus ultra:

Code: Select all

	for k in List
		!x ? x:="abcd " A_Index-99 : ""
This is ~74% faster!
P.s.: I got it already before, but I didn't think to this concatenation!
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Code Puzzle Thread

07 Dec 2017, 18:51

These methods break the function. Regarding,

Code: Select all

for , l in list
it probably doesn't do what you think.

Cheers.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Code Puzzle Thread

08 Dec 2017, 02:26

I know something is wrong, since it works only if I know the content of the List.
Yes, you are right! I actually even don't understand why this

Code: Select all

for k, l in List
	x:=l
works! I just have a hunch that the function must somehow process the x and l in order to make comparison.

P.s.: I'm desperately waiting for the right solution and at least raw explanation, but of course let's wait if somebody else has an idea. Meanwhile I'll give a try now and then.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Code Puzzle Thread

08 Dec 2017, 13:03

This is my best till now:

Code: Select all

	for k, x in List
		continue
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Code Puzzle Thread

11 Dec 2017, 08:04

Hi Helgef,

do you think about something like

Code: Select all

Min(List*)
{	; https://autohotkey.com/boards/viewtopic.php?f=6&t=40898 by FanaticGuru
	!(X := List[List.MaxIndex()]) ? List._NewEnum().Next( , X) : ""
for the special case?

Edit: Modified to match the rules.
Last edited by just me on 11 Dec 2017, 08:33, edited 1 time in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Code Puzzle Thread

11 Dec 2017, 08:24

Hello just me, I'm happy to see you participate :wave:
I'm on the phone so I can't test, but it looks like it will achieve the goal, but it doesn't follow the rules, specifically pop will modify the object refered to by the variable list.

Cheers.
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Code Puzzle Thread

11 Dec 2017, 08:28

Hi,

I missed that. I modified my post.
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Code Puzzle Thread

11 Dec 2017, 13:59

Here is my solution.

Code: Select all

Min(List*)
{	; https://autohotkey.com/boards/viewtopic.php?f=6&t=40898 by FanaticGuru
	Enum := List._NewEnum(), Enum.Next(Y), Enum.Next(,X)
	for key, element in List	; This line is not allowed to be modified.
		if (element < X)        ; This line is not allowed to be modified.
			X := element        ; This line is not allowed to be modified.
	return X
}
Basically you don't want X to be the first element in the List array because the first element is a huge string and you want to avoid comparing the first element to itself as that will be the comparision of two huge strings. This solution makes X the second element in the array which pretty much cuts the time by about 50% in this special case but has little impact plus or minus in most cases.

Here is a superior solution:

Code: Select all

Min(X:="�", List*)	; X := chr(0xffff)
{	; https://autohotkey.com/boards/viewtopic.php?f=6&t=40898 by FanaticGuru
	for key, element in List	; This line is not allowed to be modified.
		if (element < X)        ; This line is not allowed to be modified.
			X := element        ; This line is not allowed to be modified.
	return X
}
This deletes one line entirely and changes the function parameters so that X is defined right from the get go. This cuts the time by about 75% in this special case and cuts the time significantly in all cases.

That X default is a special character. Basically a very high special character so that all characters and numbers are lower than the initial X. You need to save your file in an unicode encoding that will allow that special character. I use UTF-16 Little Endian but any UTF should work. The special character is a little bit of a pain but worth the universal improvement in the functions performance.

The superior solution is pretty much entirely the work of Helgef with my imput only being maybe inspiration.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Code Puzzle Thread

11 Dec 2017, 14:17

Very good just me :clap:. That is a point for you.

Thank you FanaticGuru for the explaination and sharing your function :thumbup:. Although it is implied by your explaination, I would like to emphasise that the huge compairsion also comes with the burden of making one huge string copy, which takes time.

Another example, showing the time spent on copying the data is, using just me's solution as an example,

Code: Select all

Min(List)	; Removed *
{	; https://autohotkey.com/boards/viewtopic.php?f=6&t=40898 by FanaticGuru
	!(X := List[List.MaxIndex()]) ? List._NewEnum().Next( , X) : ""
	for key, element in List	; This line is not allowed to be modified.
		if (element < X)        ; This line is not allowed to be modified.
			X := element        ; This line is not allowed to be modified.
	return X
}
Min(p) ; Removed *
Here we aviod copying the string entirely, this breaks the rules ofc.

@ rommmcek, you where close, for example, this,

Code: Select all

for k, x in List
	continue
avoids the huge compairson, but does the copy. You could have done,

Code: Select all

for k in List
	if (A_Index == 2) 
		break
X := List[k]
Finally, it is now just me's privilige to provide the next puzzle, if just me so pleases within some reasonable time frame.

Cheers.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Code Puzzle Thread

12 Dec 2017, 04:05

Awesome tractates!
One think I still don't understand. Why count to two? Why not just simply use X:=List[2] instead?, knowing what is at the second place. And then why would X:="abcd 1" break the function? Any way I do understand this things a bit better now.
Bye!

P.s.: In FG's superior solution Min(X:="�", List*) for me works if I assign anything to X even X:=""?
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Code Puzzle Thread

12 Dec 2017, 04:28

Hi Helgef,

I don't think I deserve the point. I didn't expect that copying a large string would cost so much time. I thought it was caused by the additional List._NewEnum() so i tried to avoid it, if possible. I was wrong. So my "solution" is pure coincidence.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Code Puzzle Thread

12 Dec 2017, 06:41

If anything, your honesty would award you an additional point just me, the puzzle rules didn't demand an explaination, you have been added to the scoreboard. You will get one more if you supply the next puzzle :).

Also, you have an good point about the additional enumerator, it is a wasteful, it is possible to continue the for loop with the same enumerator, but any such solutions will probably come with a higher price than making a new.

@ rommmcek
Why not just simply use X:=List[2] instead?
The function must work for any input the original does, eg, Min(1) will return blank if you do that. If you do X:="abcd 1" and call the function like this, Min("x","y") you will get back "abcd 1" instead of x.
works if I assign anything to X even X:=""?
The default value is not used when X is assigned a value from the call, hence in those cases, it can be anything. When you call the function like Min(AssociativeArray*) , and AssociativeArray doesn't only have numeric keys like 1,2,... and lacks a key named X, the X parameter's default value is used, example, Min({a:1,b:2}*) and Min({a:1, x:0}*).

Cheers.
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Code Puzzle Thread

12 Dec 2017, 14:01

rommmcek wrote:Awesome tractates!
One think I still don't understand. Why count to two? Why not just simply use X:=List[2] instead?, knowing what is at the second place. And then why would X:="abcd 1" break the function? Any way I do understand this things a bit better now.
Bye!

P.s.: In FG's superior solution Min(X:="�", List*) for me works if I assign anything to X even X:=""?
As Helgef touched on the tricky part is associative arrays.

For example:

Code: Select all

List := {one:1, two:2}
MsgBox % List[2]	; this does not work as there is no key equal to "2", the only keys are "one" and "two"
This is the whole rigmarole with _NewEnum(). How to get the second element of an array when you don't know the keys.

The X:="�" is only to deal with associative arrays.

This might help to understand how the parameters are assigned values.

Code: Select all

Func1(1,2)
Func1(X:="�", List*)
{
	MsgBox % X "`n" List[1]
}

Data := {one:1}
Func2(Data*)
Func2(X:="�", List*)
{
	MsgBox % X "`n" List["one"]
}

In the first function, 1 goes into X as a simple variable and 2 goes into List as a simple array.

In the second function, Data associative array does not assign to X as it is not set up to accept an array so X defaults to � and all the passed info from Data gets assigned to List as an associative array.

In both functions no matter what List is going to be an array of information even if it ends up List := {} with nothing in it.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Code Puzzle Thread

13 Dec 2017, 16:18

Thanks Helgef and special acknowledgment this time to FG!

Maybe these were still not the last stones in my array mosaic, but very precious ones for sure!
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Code Puzzle Thread

05 Jan 2018, 14:44

Puzzle 9: Release the bug.
In this puzzle we shall look at a benchmarking script which contains a significant error, which causes incorrect results for the last test snippet. The test measures the time it takes to free count := 50000 instances of the class Task. All instances are stored internally in the array Task.List, hence in order to invoke __delete they must be removed from this array.

Puzzle objectives: Correct the significant mistake in the benchmarking script in the code box below.
Puzzle rules: You are not allowed to modify the class Task. You must be able to explain the mistake, hence, why your solution works.
Puzzle hint: When you correct the mistake, you can expect the last test snippet to be significantly faster. Edit: When you correct the mistake, you can expect the last test to work as intended.
Code:
The code comes from this discussion: [BUG]Associative Arrays, you are not required to read the discussion to solve the problem. Reading others' code and debug it can be very challenging, I consider that part of this puzzle and therefore I have not removed any noise from the code.

Code: Select all

;	https://autohotkey.com/boards/viewtopic.php?f=37&t=42328
;	[BUG]Associative Arrays
setbatchlines,-1
#noenv

class Task {
	static time:= 0
	static tick:= 0
	static List:= []
	__new(name, mode:= 0x13) {
		this.mode:= mode
		this.name:= name
		Task.List[this]:= "" ;no value for key
	}
	end() {	 ;initate destruct
		if !Task.time
			Task.time:= A_TickCount
		Task.List.Delete(this) ;self kill
	}
	;Task.List.Delete(this)
	;Task.List:= ""
	__delete() { ;destruct idea by Helgef
		if !Task.time
			Task.time:= A_TickCount
		this.name:= ""
		Task.tick:= A_TickCount - Task.time
	}
}

result:= ""
count:= 50000
; SLOW -----------------------------------------------
loop % count
	new Task("name" A_Index)
Task.time:= ""
SLOW:
	for key in Task.List {
		key.end()
		goto SLOW
	}
key:=""
msgBOX(result.= "SLOW`t:= " Task.tick "`n")
; FAST -----------------------------------------------
array:= []
loop % count
	new Task("name" A_Index)
Task.time:= ""
	for key in Task.List
		array[A_Index]:= key
	loop % array.length()
		array[A_Index].end()
	array:= ""
key:=""
msgBOX(result.= "FAST`t:= " Task.tick "`n")
; ENUM -----------------------------------------------
loop % count
	new Task("name" A_Index)
Task.time:= ""
while (_enum:= Task.List._newEnum()).Next(key, val) {
	loop {
		key.end()
	} until !_enum.Next(key, val)	
}
key:=""
msgBOX(result.= "ENUM`t:= " Task.tick "`n")
; LOOP -----------------------------------------------
loop % count
	new Task("name" A_Index)
Task.time:= ""
loop {
	isEmpty:= 1
	for key in Task.List {
		key.end()
		isEmpty:= 0
	}
} until isEmpty
key:="" ; <-- edit: conversion mistake fixed
msgBOX(result.= "LOOP`t:= " Task.tick "`n")
; Helgef ---------------------------------------------
loop % count
	new Task("name" A_Index)
Task.time:= ""
Task.List:= [] ;Task.List:= "" change type from Array to string if further use
msgBOX("Wait for Helgef",, "2") ;this 2 seconds is out of tick (destruction in background)
msgBOX(result.= "HELL`t:= " Task.tick "`n")

msgBOX(a,b:="",c:=""){
	msgbox,,,% a, % c
}
The code has been converted from v2 to v1, if you spot a mistake in that regard please tell.

Good luck.
Last edited by Helgef on 08 Jan 2018, 13:55, edited 2 times in total.
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Code Puzzle Thread

06 Jan 2018, 06:44

Hi Helgef,

I'd say
Puzzle hint: When you correct the mistake, you can expect the last test to work as intended.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Code Puzzle Thread

06 Jan 2018, 06:53

Hello just me, that is correct :) .

Cheers.
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Code Puzzle Thread

08 Jan 2018, 07:16

Another hint: If you compare the results of the LOOP and Helgef sections, you'll see that they are always equal.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Code Puzzle Thread

08 Jan 2018, 13:58

How is it going just me? I thought you had solved it when you corrected my hint. Your new hint is correct, but is it a good hint? ;)
Anyways, I have corrected a small conversion error, it is not significant for the puzzle though. I also updated the first post to indicate the current puzzle.

Good luck, have fun :wave:

Return to “General Discussion”

Who is online

Users browsing this forum: No registered users and 12 guests