Code Puzzle Thread

Post a reply


In an effort to prevent automatic submissions, we require that you complete the following challenge.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :| :mrgreen: :geek: :ugeek: :arrow: :angel: :clap: :crazy: :eh: :lolno: :problem: :shh: :shifty: :sick: :silent: :think: :thumbup: :thumbdown: :salute: :wave: :wtf: :yawn: :facepalm: :bravo: :dance: :beard: :morebeard: :xmas: :HeHe: :trollface: :cookie: :rainbow: :monkeysee: :monkeysay: :happybday: :headwall: :offtopic: :superhappy: :terms: :beer:
View more smilies

BBCode is ON
[img] is OFF
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Code Puzzle Thread

Re: Code Puzzle Thread

by nnnik » 25 May 2018, 14:06

Well I really searched for a solution myself for quite a while as it was a problem that I couldnt solve myself.
I was rather impressed at the speed he came up with the solution.
Also while Helgefs solution solves this riddle but does not solve the underlying problem for me since the underlying problem does not allow the addition of a static initialisation by writing a new function.
In AHK v1.1.29.00 you can use ObjGetBase and ObjSetBase to solve this.

Re: Code Puzzle Thread

by Helgef » 25 May 2018, 13:05

I think it is time for a new puzzle, I leave it open to anyone who likes to submit one to do so, please see the rules in the first post and do not hesitate to ask me (via pm) if you have any questions.

This is my (pre-1.1.29.00) suggestion for a solution to nnnik's puzzle,

Code: Select all

;add code here
objrawset(f(), "__set", "")
objrawset(f(), "__get", "")
objrawset(f(), "__call", "")

f(){
	static b := proxy
	return b
}
;don't edit the code below
Cheers.

Re: Code Puzzle Thread

by Helgef » 12 Mar 2018, 06:41

It seems nnnik's puzzle remains unsolved, great :D. Maybe it is time for a hint?

I have posted a bonus puzzle here, if someone wants to ponder it, it assumes some understanding of c/c++ so it is not fit for this thread.

Cheers

Re: Code Puzzle Thread

by derz00 » 03 Feb 2018, 17:13

This puzzle strikes my interest, but only in that I would like to learn more about classes. So I can't solve it :(

Re: Code Puzzle Thread

by Helgef » 02 Feb 2018, 04:49

Thank you nnnik, I will mark this as the current puzzle. You will get one point for submitting a new puzzle.

Cheers.

Re: Code Puzzle Thread

by nnnik » 02 Feb 2018, 04:26

Puzzle:
Goals:
Disconnect the Proxy from the Target
Restrictions:
You may not edit the underlying object in memory with numput/get or similar.
You may only add new code in the marked area.

Code: Select all

;add code here

;don't edit the code below
class Proxy {
	__New() {
		static init := new Proxy()
		if init
			return init
		Proxy := this
	}
	__Call( fn, p* ){
		return Target[fn]( p* )
	}
	__Set( p* ) {
		value := p.pop()
		return Target[p*] := value
	}
	__Get( p* ){
		return Target[p*]
	}
}
class Target {
	__New() {
		static init := new Target()
		if init
			return init
		Target := this
		this.val := 13
	}
	test() {
		Msgbox Hello World!
	}
}

Re: Code Puzzle Thread

by Mariaspencer » 24 Jan 2018, 02:06

I was also waiting for the 3D formula to apply in the game.

Re: Code Puzzle Thread

by _3D_ » 10 Jan 2018, 03:36

just me wrote:_enum := "" ; <<<<< added
Cheers ;) .
Yep my mistake.

Code: Select all

class Task {
	static time:= 0
	static tick:= 0
	static List:= []
	__new(name, mode:= 0x13) {
		this.mode:= mode
		this.name:= name
		Task.List[this]:= ""
	}
	static end:= func("__Task_end")
	__delete() { ;destruct idea by Helgef
		if !Task.time
			Task.time:= A_TickCount
		if this.mode != "" { ;prevent second run
			;on destruct actions <<< ----------------------------------	;
			this.mode:= this.name:= "" ;clear to prevent second run  	;
		}																;
		Task.tick:= A_TickCount - Task.time								;
}	}																	;
__Task_end(byRef this) {												;
	if !Task.time														;
		Task.time:= A_TickCount											;
	this.__delete()			; forced call on destruct actions	<<< ---	;
	Task.List.Delete(this)	; remove reference from Task.List
	this:= "" ;if no more references <<< destruct
}

result:= ""
count:= 50000
;count:= 20
; LOOP -----------------------------------------------
loop count
	new Task("name" A_Index)
Task.time:= ""
while !isEmpty { ;just less code but the same
	isEmpty:= 0
	for key in Task.List {
		key.end()
		isEmpty:= 1 
}	}
msgBOX(result.= "LOOP`t:= " Task.tick "`n") ;<<< 1391
; Helgef ---------------------------------------------
loop count
	new Task("name" A_Index)
Task.time:= "" ;Task.time:= 0 (the same)
Task.List:= []
;next line is needed to become destruction ready
;there count times calling of Task.__delete()
;but the fastest way
msgBOX("Wait for Helgef",, "T1") ;1 seccond enough
msgBOX(result.= "HELL`t:= " Task.tick "`n") ;<<<  234 (fastest)
Ty guys!

Re: Code Puzzle Thread

by Helgef » 09 Jan 2018, 12:23

You are spot on just me, both in regards to reasoning, explaination and solution, great job :thumbup:. You will be rewarded a point.

Since just me already declined the offer to submit a new puzzle, it is free for anyone who likes to, to do so.

Cheers.

Re: Code Puzzle Thread

by just me » 09 Jan 2018, 11:27

And the answer is: 42!

Athough it should always be true, it's obviously not true in this case. I tried without success. After that I noticed, that the LOOP and the Helgef sections always give the same result, regardless of the value in Count. So I added Task.tick := 0 above Task.List:= []. The Helgef section was indeed 'significant faster' after doing this: 0 ms for 50,000 Task instances, WOW! :shock:

This seemed to be a little too fast. I realized that Task.tick isn't touched by Task.List:= [] at all. From this follows that Task.__delete() is not called. The only reason for this behaviour is: The objects are not released because 'something' still holds a reference. Some thoughts later I found this 'something'. It's the enumerator object created by while (_enum:= Task.List._newEnum()) in the ENUM section. So the real answer is:

Code: Select all

; 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:=""
_enum := ""	; <<<<< added
msgBOX(result.= "ENUM`t:= " Task.tick "`n")
Due to my limited knowledge about OOP and the AHK implementation details my explanation might be technically imprecise, but the solution is working.

Cheers ;) .

Re: Code Puzzle Thread

by Helgef » 09 Jan 2018, 08:21

:thumbup:. submitting new puzzles aren't mandatory, you are welcome to submit your solution whenever you like.

Cheers :wave: .

Re: Code Puzzle Thread

by just me » 09 Jan 2018, 07:21

Hi Helgef,

yes, I think I solved it, but I'm waiting for others who might jump in (because I won't contribute a new puzzle).
My last hint has been my personal key to solve the problem.

:wave:

Re: Code Puzzle Thread

by Helgef » 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:

Re: Code Puzzle Thread

by just me » 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.

Re: Code Puzzle Thread

by Helgef » 06 Jan 2018, 06:53

Hello just me, that is correct :) .

Cheers.

Re: Code Puzzle Thread

by just me » 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.

Re: Code Puzzle Thread

by Helgef » 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.

Re: Code Puzzle Thread

by rommmcek » 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!

Re: Code Puzzle Thread

by FanaticGuru » 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

Re: Code Puzzle Thread

by Helgef » 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.

Top