Split specified number into parts and sum Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Split specified number into parts and sum

04 Sep 2017, 21:06

Hello all, allow me to ask a difficult(for me) script, i'll go in straight to the thread. :)

vNumber: 30000
I need to split a specified vNumber into 4 parts, each parts are close to each other (I mean Roughly average)

condition one: each parts can be devided exactly by 48
condition two: each parts need to mulply by specified number (see the samples in the list below)
condition three: in the final, add them together, the vResult must be greater than the vNumber (between 10~50 greater), but lower than the vNumber is not acceptble.

here's an example:
vNumber: 30000
  • 1152(;assume this is q1)*7.25(assume this is p1)=8352.00(assume this is t1)
    1152(q2)*6.53(p2)=7522.56(t2)
    1200*(q3)6.16(p3)=7392.00(t3)
    1248(q4)*5.43(p4)=6776.64(t4)
    vResult := t1+t2+t3+t4(i.e. 30043.20)
another example:

vNumber: 160000
  • 6240(;assume this is q1)*7.25(assume this is p1)=45240.00(assume this is t1)
    6240(q2)*6.53(p2)=40747.20(t2)
    6432*(q3)6.16(p3)=39621.12(t3)
    6336(q4)*5.43(p4)=34404.48(t4)
    vResult := t1+t2+t3+t4(i.e. 160012.80)
it' s been very valuable with your help, appreciate.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Split specified number into parts and sum

04 Sep 2017, 21:31

If the questions in brackets are answered, then perhaps a script can be written for this.
vNumber = 30000
30010 <= vResult <= 30050 (is this correct?)
q1 to q4: divisible by 48
q1 to q4: close to each other (how close?) [EDIT: Also, perhaps specify maximum/minimum values for these numbers.]
p1 to p4: of the form #.## (is this correct, are the conditions more restrictive than this?) [EDIT: Actually these numbers are constant right? They don't change.]
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

04 Sep 2017, 22:21

jeeswg wrote:If the questions in brackets are answered, then perhaps a script can be written for this.
vNumber = 30000
30010 <= vResult <= 30050 (is this correct?)
q1 to q4: divisible by 48
q1 to q4: close to each other (how close?) [EDIT: Also, perhaps specify maximum/minimum values for these numbers.]
p1 to p4: of the form #.## (is this correct, are the conditions more restrictive than this?) [EDIT: Actually these numbers are constant right? They don't change.]
30010 <= vResult <= 30050 (Correct)
q1 to q4: divisible by 48
q1 to q4: close to each other (how close?) i think it's 3 times greater or lower than 48 compare with q1-q4 (for example maximum:1248, minimum:1152)
p1 to p4: correct, yes these numbers are constant yes
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Split specified number into parts and sum

04 Sep 2017, 22:54

I've adapted my code from:
Generate Random numbers and sum to specific given number - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=36532
And it looks to be working quite well. Although I believe the criteria in the first example is too restrictive, and so you only get 1 possible answer, it does work quite well for the second example, with 10 possible answers.

Code: Select all

q::
vNumber := 30000, vRangeQ1 := 1152, vRangeQ2 := 1248, vDiff := 48
vNumber := 160000, vRangeQ1 := 6240, vRangeQ2 := 6432, vDiff := 48

oP := [7.25,6.53,6.16,5.43]
vRangeT1 := vNumber + 10
vRangeT2 := vNumber + 50
;vRangeR1 := 0
;vRangeR2 := Floor((vRangeQ2-vRangeQ1)/vDiff)
Loop, % oP.Length()
	vP%A_Index% := oP[A_Index]
o1 := [vRangeQ1,vRangeQ1,vRangeQ1,vRangeQ1]
o2 := [vRangeQ2,vRangeQ2,vRangeQ2,vRangeQ2]
;o1 := [vRangeR1,vRangeR1,vRangeR1,vRangeR1]
;o2 := [vRangeR2,vRangeR2,vRangeR2,vRangeR2]

vCount := o1.Length()
o := o1.Clone(), o.0 := 0
vOutput := ""
Loop
{
	vSum := o.1*vP1+o.2*vP2+o.3*vP3+o.4*vP4
	if (vSum >= vRangeT1) && (vSum <= vRangeT2)
		vOutput .= Format("{:i}*{:s}+{:i}*{:s}+{:i}*{:s}+{:i}*{:s} = {:0.2f}", o.1,vP1,o.2,vP2,o.3,vP3,o.4,vP4, vSum) "`r`n"
	o[vCount] += vDiff
	Loop, % vCount
	{
		vIndex := vCount+1-A_Index
		if (o[vIndex] > o2[vIndex])
			o[vIndex] := o1[vIndex], o[vIndex-1] += vDiff
	}
	if (o.0)
		break
}
Clipboard := vOutput
MsgBox, % vOutput
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

05 Sep 2017, 01:19

jeeswg wrote:I've adapted my code from:
Generate Random numbers and sum to specific given number - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=36532
And it looks to be working quite well. Although I believe the criteria in the first example is too restrictive, and so you only get 1 possible answer, it does work quite well for the second example, with 10 possible answers.

Code: Select all

q::
vNumber := 30000, vRangeQ1 := 1152, vRangeQ2 := 1248, vDiff := 48
vNumber := 160000, vRangeQ1 := 6240, vRangeQ2 := 6432, vDiff := 48

oP := [7.25,6.53,6.16,5.43]
vRangeT1 := vNumber + 10
vRangeT2 := vNumber + 50
;vRangeR1 := 0
;vRangeR2 := Floor((vRangeQ2-vRangeQ1)/vDiff)
Loop, % oP.Length()
	vP%A_Index% := oP[A_Index]
o1 := [vRangeQ1,vRangeQ1,vRangeQ1,vRangeQ1]
o2 := [vRangeQ2,vRangeQ2,vRangeQ2,vRangeQ2]
;o1 := [vRangeR1,vRangeR1,vRangeR1,vRangeR1]
;o2 := [vRangeR2,vRangeR2,vRangeR2,vRangeR2]

vCount := o1.Length()
o := o1.Clone(), o.0 := 0
vOutput := ""
Loop
{
	vSum := o.1*vP1+o.2*vP2+o.3*vP3+o.4*vP4
	if (vSum >= vRangeT1) && (vSum <= vRangeT2)
		vOutput .= Format("{:i}*{:s}+{:i}*{:s}+{:i}*{:s}+{:i}*{:s} = {:0.2f}", o.1,vP1,o.2,vP2,o.3,vP3,o.4,vP4, vSum) "`r`n"
	o[vCount] += vDiff
	Loop, % vCount
	{
		vIndex := vCount+1-A_Index
		if (o[vIndex] > o2[vIndex])
			o[vIndex] := o1[vIndex], o[vIndex-1] += vDiff
	}
	if (o.0)
		break
}
Clipboard := vOutput
MsgBox, % vOutput
return
Hi, the output was nice, but it works only for vNumber := 30000 vNumber := 160000, I think you may misunderstand my mean, the vNumber 30000/160000 is just an example ...not constant numbers,
my thought is the vNumber will be put in

Code: Select all

Gui, Add, Edit, w600 vNumber
by manually,it can be 30000, 53698, 60000, 49999, 224316 ...etc
anyway, can i call any one of them(as #1 floor's q1 p1 t1 result) using the

Code: Select all

Clipboard := vP1 Clipboard := vP2 Clipboard := vP3
... etc?

edit: by the way, the q1 q2 q3 q4's value can be as close as possible,but not a much necessary condition, the result is the need
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Split specified number into parts and sum

05 Sep 2017, 09:55

I have all the key ideas in the code, the best thing would be for you to try to fine-tune the code yourself, and if you're still having problems then you could post some code and I could take a look.

What I suggest you do is choose some formula that given vNumber, then chooses vRangeQ1, vRangeQ2 and vDiff.

Another idea is to compare vTotal, against a variable, say vTotalMin or vTotalMax, the smallest or biggest value so far, to get something like:

Code: Select all

if (vTotal < vTotalMin)
	vTotalMin := vTotal
Anyway at some point you'll have to completely understand and take responsibility for all the mathematics. Best of luck.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Split specified number into parts and sum  Topic is solved

06 Sep 2017, 10:26

I spent some time trying to find/create some 'smart' algorithm, but failed. So (hopefully) here is a brute-force solution. It might need some additional input checking to be foolproof:

Code: Select all

#NoEnv
SetBatchLines, -1
; Constant multipliers -----------------------------------------------------------------------------------------------------------
P1 := 7.25
P2 := 6.53
P3 := 6.16
P4 := 5.43
; GUI ----------------------------------------------------------------------------------------------------------------------------
Gui, Margin, 10, 10
Gui, Add, Text, xm ym w200, Amount:
Gui, Add, Edit, xp y+2 wp Number vAmount, 30000
Gui, Add, Text, ym wp, Minimum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMinD, 10
Gui, Add, Text, ym wp, Maximum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMaxD, 50
Gui, Add, Text, xm wp Section, Maximum Iterations:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDI Range1-3, 3
Gui, Add, Text, ys, Maximum Results:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 15
Gui, Add, UpDown, vUDR Range1-30, 15
Gui, Add, Text, ys, Maximum Delta (n * 48):
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDD Range1-5, 3
Gui, Add, Text, xm, Results:
Gui, Add, ListView, xm y+2 w620 r15, #|Q1|Q2|Q3|Q4|Result|Max Delta|%A_Space%
Loop, % LV_GetCount("Column") - 1
   LV_ModifyCol(A_Index, "Integer")
Gui, Add, Button, xm wp gCalculate, Calculate
Gui, Add, StatusBar
Gui, Show, , Calculator
Return
; Exit ---------------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; Calculate the results ----------------------------------------------------------------------------------------------------------
Calculate:
Gui, +OwnDialogs
Gui, Submit, NoHide
;
Num := Amount
Min := Num + MinD
Max := Num + MaxD
MaxLoopCount := UDI
MaxResults := UDR
MaxDelta := UDD * 48
;
Q := Floor(Num // (P1 + P2 + P3 + P4))
Q -= Mod(Q, 48)
If (Q < MaxDelta) {
   MsgBox, 16, %A_ThisLabel%, Cannot iterate %UDI% times!
   GuiControl, Focus, UDI
   Return
}
LV_Delete()
;
Results := []
Loop {
   Q1 := Q2 := Q3 := Q4 := Q
   S1 := Q1 * P1
   Loop {
      S2 := S1 + (Q2 * P2)
      If (S2 >= Min)
         Break
      Q3 := Q
      Loop {
         S3 := S2 + (Q3 * P3)
         If (S3 >= Min)
            Break
         Q4 := Q
         Loop {
            S4 := S3 + (Q4 * P4)
            If (S4 >= Min) {
               If (S4 <= Max) {
                  R := (Q1 * P1) + (Q2 * P2) + (Q3 * P3) + (Q4 * P4)
                  D := 0
                  If ((Q2 - Q) > D)
                     D := Q2 - Q
                  If ((Q3 - Q) > D)
                     D := Q3 - Q
                  If ((Q4 - Q) > D)
                     D := Q4 - Q
                  If (D <= MaxDelta)
                     Results.Push([Q1, Q2, Q3, Q4, Round(R, 2), D])
                  If !(Results.Length() < MaxResults)
                     Break, 4
               }
               Break
            }
            Q4 += 48
         }
         Q3 += 48
      }
      Q2 += 48
   }
   Q -= 48
} Until (A_Index >= MaxLoopCount)
;
For I, R In Results
   LV_Add("", A_Index, R*)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
LV_ModifyCol(7, "Sort")
L := Results.Length()
SB_SetText("   Found " . L . " solution" . (L <> 1 ? "s." : "."))
Return
Out of curiosity: For what do you need this?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Split specified number into parts and sum

06 Sep 2017, 16:54

Nice gui Just me :thumbup:
The question is not very well specified imo, you can find an infinite number of solutions. It is very simple arithmetics to find solutions, which aren't more specific than described in the first post. Here is a simple example, there are some random parameters to vary the result,

Code: Select all

/*
condition one: each parts can be devided exactly by 48
condition two: each parts need to mulply by specified number (see the samples in the list below)
condition three: in the final, add them together, the vResult must be greater than the vNumber (between 10~50 greater), but lower than the vNumber is not acceptble.
*/
vNumber := 30000	
in := vNumber // 4
q:=[]
p:=[]
t:=[]

; Multiple of 48, q[i]/48 ∈ (rP1, rP2). Keep as close as you like.
rP1:=30		
rP2:=34
minDt:=10	; result Min max deviation from vNumber
maxDt:=50
loop 4
{
	i := A_Index
	q[i] := 48 * rand(rP1,rP2)
	p[i] := (in + rand(minDt,maxDt)/4) / q[i]
	t[i]:=q[i]*p[i]
}
; sum result
s:=0
for k, v in t
	s+=v
msgbox % 	"q:`t" q[1] "`t" q[2] "`t" q[3] "`t" q[4] "`n" 
		.	"p:`t" round(p[1],2) "`t" round(p[2],2) "`t" round(p[3],2) "`t" round(p[4],2) "`n" ; Round only for display
		.	"t:`t" round(t[1],2) "`t" round(t[2],2) "`t" round(t[3],2) "`t" round(t[4],2) "`n" 
		.	"result:`t" s "`n" 
		.	"in:`t" vNumber "`n" 
		.	"diff:`t" s-vNumber "`t(min,max) = (" minDt "," maxDt ")`n" 
		
rand(min,max){
	random r,min,max
	return r
}
I am too interested in what this is for, if it was clearly specified, you would probably have got a different answer.

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

Re: Split specified number into parts and sum

07 Sep 2017, 03:07

Hi Helgef,
ivill wrote:viewtopic.php?p=168830#p168830

30010 <= vResult <= 30050 (Correct)
q1 to q4: divisible by 48
q1 to q4: close to each other (how close?) i think it's 3 times greater or lower than 48 compare with q1-q4 (for example maximum:1248, minimum:1152)
p1 to p4: correct, yes these numbers are constant yes
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Split specified number into parts and sum

07 Sep 2017, 17:03

(how close?) i think it's...
:facepalm: :lol:
Anyways, nice one just me, it seems to solve the problem. :thumbup:
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

08 Sep 2017, 01:02

jeeswg wrote:I have all the key ideas in the code, the best thing would be for you to try to fine-tune the code yourself, and if you're still having problems then you could post some code and I could take a look.

What I suggest you do is choose some formula that given vNumber, then chooses vRangeQ1, vRangeQ2 and vDiff.

Another idea is to compare vTotal, against a variable, say vTotalMin or vTotalMax, the smallest or biggest value so far, to get something like:

Code: Select all

if (vTotal < vTotalMin)
	vTotalMin := vTotal
Anyway at some point you'll have to completely understand and take responsibility for all the mathematics. Best of luck.
Thank you @jeeswg, i fully understand your meaning, that i should take responsibility and do more learning and make it done, though i am a newbie, but i will keep doing my best.
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

08 Sep 2017, 01:11

just me wrote:I spent some time trying to find/create some 'smart' algorithm, but failed. So (hopefully) here is a brute-force solution. It might need some additional input checking to be foolproof:

Code: Select all

#NoEnv
SetBatchLines, -1
; Constant multipliers -----------------------------------------------------------------------------------------------------------
P1 := 7.25
P2 := 6.53
P3 := 6.16
P4 := 5.43
; GUI ----------------------------------------------------------------------------------------------------------------------------
Gui, Margin, 10, 10
Gui, Add, Text, xm ym w200, Amount:
Gui, Add, Edit, xp y+2 wp Number vAmount, 30000
Gui, Add, Text, ym wp, Minimum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMinD, 10
Gui, Add, Text, ym wp, Maximum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMaxD, 50
Gui, Add, Text, xm wp Section, Maximum Iterations:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDI Range1-3, 3
Gui, Add, Text, ys, Maximum Results:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 15
Gui, Add, UpDown, vUDR Range1-30, 15
Gui, Add, Text, ys, Maximum Delta (n * 48):
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDD Range1-5, 3
Gui, Add, Text, xm, Results:
Gui, Add, ListView, xm y+2 w620 r15, #|Q1|Q2|Q3|Q4|Result|Max Delta|%A_Space%
Loop, % LV_GetCount("Column") - 1
   LV_ModifyCol(A_Index, "Integer")
Gui, Add, Button, xm wp gCalculate, Calculate
Gui, Add, StatusBar
Gui, Show, , Calculator
Return
; Exit ---------------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; Calculate the results ----------------------------------------------------------------------------------------------------------
Calculate:
Gui, +OwnDialogs
Gui, Submit, NoHide
;
Num := Amount
Min := Num + MinD
Max := Num + MaxD
MaxLoopCount := UDI
MaxResults := UDR
MaxDelta := UDD * 48
;
Q := Floor(Num // (P1 + P2 + P3 + P4))
Q -= Mod(Q, 48)
If (Q < MaxDelta) {
   MsgBox, 16, %A_ThisLabel%, Cannot iterate %UDI% times!
   GuiControl, Focus, UDI
   Return
}
LV_Delete()
;
Results := []
Loop {
   Q1 := Q2 := Q3 := Q4 := Q
   S1 := Q1 * P1
   Loop {
      S2 := S1 + (Q2 * P2)
      If (S2 >= Min)
         Break
      Q3 := Q
      Loop {
         S3 := S2 + (Q3 * P3)
         If (S3 >= Min)
            Break
         Q4 := Q
         Loop {
            S4 := S3 + (Q4 * P4)
            If (S4 >= Min) {
               If (S4 <= Max) {
                  R := (Q1 * P1) + (Q2 * P2) + (Q3 * P3) + (Q4 * P4)
                  D := 0
                  If ((Q2 - Q) > D)
                     D := Q2 - Q
                  If ((Q3 - Q) > D)
                     D := Q3 - Q
                  If ((Q4 - Q) > D)
                     D := Q4 - Q
                  If (D <= MaxDelta)
                     Results.Push([Q1, Q2, Q3, Q4, Round(R, 2), D])
                  If !(Results.Length() < MaxResults)
                     Break, 4
               }
               Break
            }
            Q4 += 48
         }
         Q3 += 48
      }
      Q2 += 48
   }
   Q -= 48
} Until (A_Index >= MaxLoopCount)
;
For I, R In Results
   LV_Add("", A_Index, R*)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
LV_ModifyCol(7, "Sort")
L := Results.Length()
SB_SetText("   Found " . L . " solution" . (L <> 1 ? "s." : "."))
Return
Out of curiosity: For what do you need this?
Thanks @just me, i have to say your solution is the best one, anyway i can't output a selected result: Q1 Q2 Q3 Q4 Result, could you tweak it a little bit?
it's for warehousing stuff :)
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

08 Sep 2017, 01:14

Helgef wrote:Nice gui Just me :thumbup:
The question is not very well specified imo, you can find an infinite number of solutions. It is very simple arithmetics to find solutions, which aren't more specific than described in the first post. Here is a simple example, there are some random parameters to vary the result,

Code: Select all

/*
condition one: each parts can be devided exactly by 48
condition two: each parts need to mulply by specified number (see the samples in the list below)
condition three: in the final, add them together, the vResult must be greater than the vNumber (between 10~50 greater), but lower than the vNumber is not acceptble.
*/
vNumber := 30000	
in := vNumber // 4
q:=[]
p:=[]
t:=[]

; Multiple of 48, q[i]/48 ∈ (rP1, rP2). Keep as close as you like.
rP1:=30		
rP2:=34
minDt:=10	; result Min max deviation from vNumber
maxDt:=50
loop 4
{
	i := A_Index
	q[i] := 48 * rand(rP1,rP2)
	p[i] := (in + rand(minDt,maxDt)/4) / q[i]
	t[i]:=q[i]*p[i]
}
; sum result
s:=0
for k, v in t
	s+=v
msgbox % 	"q:`t" q[1] "`t" q[2] "`t" q[3] "`t" q[4] "`n" 
		.	"p:`t" round(p[1],2) "`t" round(p[2],2) "`t" round(p[3],2) "`t" round(p[4],2) "`n" ; Round only for display
		.	"t:`t" round(t[1],2) "`t" round(t[2],2) "`t" round(t[3],2) "`t" round(t[4],2) "`n" 
		.	"result:`t" s "`n" 
		.	"in:`t" vNumber "`n" 
		.	"diff:`t" s-vNumber "`t(min,max) = (" minDt "," maxDt ")`n" 
		
rand(min,max){
	random r,min,max
	return r
}
I am too interested in what this is for, if it was clearly specified, you would probably have got a different answer.

Cheers.
Hi @Helgef after all, your script is nice one, thank you!
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Split specified number into parts and sum

08 Sep 2017, 03:33

ivill wrote:... anyway i can't output a selected result: Q1 Q2 Q3 Q4 Result, could you tweak it a little bit?
What format do you need?
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

08 Sep 2017, 03:41

just me wrote:
ivill wrote:... anyway i can't output a selected result: Q1 Q2 Q3 Q4 Result, could you tweak it a little bit?
What format do you need?
%Q1% Q2% %Q3% %Q4% %result%
so that i can call each of them to do something more
Edit: how about add a button next to the "calculate", so while a row selected, press the"copy" button to save each of them as single string %Q1% Q2% %Q3% %Q4% %result%
possible?
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Split specified number into parts and sum

08 Sep 2017, 03:57

Well, I added a g-Label for the ListView. You can select a result by double click.

Code: Select all

#NoEnv
SetBatchLines, -1
; Constant multipliers -----------------------------------------------------------------------------------------------------------
P1 := 7.25
P2 := 6.53
P3 := 6.16
P4 := 5.43
; GUI ----------------------------------------------------------------------------------------------------------------------------
Gui, Margin, 10, 10
Gui, Add, Text, xm ym w200, Amount:
Gui, Add, Edit, xp y+2 wp Number vAmount, 30000
Gui, Add, Text, ym wp, Minimum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMinD, 10
Gui, Add, Text, ym wp, Maximum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMaxD, 50
Gui, Add, Text, xm wp Section, Maximum Iterations:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDI Range1-3, 3
Gui, Add, Text, ys, Maximum Results:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 15
Gui, Add, UpDown, vUDR Range1-30, 15
Gui, Add, Text, ys, Maximum Delta (n * 48):
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDD Range1-5, 3
Gui, Add, Text, xm, Results:
Gui, Add, ListView, xm y+2 w620 r15 gSelectResult, #|Q1|Q2|Q3|Q4|Result|Max Delta|%A_Space%
Loop, % LV_GetCount("Column") - 1
   LV_ModifyCol(A_Index, "Integer")
Gui, Add, Button, xm wp gCalculate, Calculate
Gui, Add, StatusBar
Gui, Show, , Calculator
Return
; Exit ---------------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; Calculate the results ----------------------------------------------------------------------------------------------------------
Calculate:
Gui, +OwnDialogs
Gui, Submit, NoHide
;
Num := Amount
Min := Num + MinD
Max := Num + MaxD
MaxLoopCount := UDI
MaxResults := UDR
MaxDelta := UDD * 48
;
Q := Floor(Num // (P1 + P2 + P3 + P4))
Q -= Mod(Q, 48)
If (Q < MaxDelta) {
   MsgBox, 16, %A_ThisLabel%, Cannot iterate %UDI% times!
   GuiControl, Focus, UDI
   Return
}
LV_Delete()
;
Results := []
Loop {
   Q1 := Q2 := Q3 := Q4 := Q
   S1 := Q1 * P1
   Loop {
      S2 := S1 + (Q2 * P2)
      If (S2 >= Min)
         Break
      Q3 := Q
      Loop {
         S3 := S2 + (Q3 * P3)
         If (S3 >= Min)
            Break
         Q4 := Q
         Loop {
            S4 := S3 + (Q4 * P4)
            If (S4 >= Min) {
               If (S4 <= Max) {
                  R := (Q1 * P1) + (Q2 * P2) + (Q3 * P3) + (Q4 * P4)
                  D := 0
                  If ((Q2 - Q) > D)
                     D := Q2 - Q
                  If ((Q3 - Q) > D)
                     D := Q3 - Q
                  If ((Q4 - Q) > D)
                     D := Q4 - Q
                  If (D <= MaxDelta)
                     Results.Push([Q1, Q2, Q3, Q4, Round(R, 2), D])
                  If !(Results.Length() < MaxResults)
                     Break, 4
               }
               Break
            }
            Q4 += 48
         }
         Q3 += 48
      }
      Q2 += 48
   }
   Q -= 48
} Until (A_Index >= MaxLoopCount)
;
For I, R In Results
   LV_Add("", A_Index, R*)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
LV_ModifyCol(7, "Sort")
L := Results.Length()
SB_SetText("   Found " . L . " solution" . (L <> 1 ? "s." : "."))
Return
; Select a result from the ListView by double click
SelectResult:
Gui, +OwnDialogs
If (A_GuiEvent = "DoubleClick") && (SelectedRow := LV_GetNext()) {
   LV_GetText(Q1, SelectedRow, 2)
   LV_GetText(Q2, SelectedRow, 3)
   LV_GetText(Q3, SelectedRow, 4)
   LV_GetText(Q4, SelectedRow, 5)
   LV_GetText(R, SelectedRow, 6)
   ; do what you want to do with the variables here
   MsgBox, 0, Selected Result, %Q1% %Q2% %Q3% %Q4% %R% ; just for testing
}
Return
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

13 Sep 2017, 08:01

just me wrote:Well, I added a g-Label for the ListView. You can select a result by double click.

Code: Select all

#NoEnv
SetBatchLines, -1
; Constant multipliers -----------------------------------------------------------------------------------------------------------
P1 := 7.25
P2 := 6.53
P3 := 6.16
P4 := 5.43
; GUI ----------------------------------------------------------------------------------------------------------------------------
Gui, Margin, 10, 10
Gui, Add, Text, xm ym w200, Amount:
Gui, Add, Edit, xp y+2 wp Number vAmount, 30000
Gui, Add, Text, ym wp, Minimum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMinD, 10
Gui, Add, Text, ym wp, Maximum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMaxD, 50
Gui, Add, Text, xm wp Section, Maximum Iterations:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDI Range1-3, 3
Gui, Add, Text, ys, Maximum Results:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 15
Gui, Add, UpDown, vUDR Range1-30, 15
Gui, Add, Text, ys, Maximum Delta (n * 48):
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDD Range1-5, 3
Gui, Add, Text, xm, Results:
Gui, Add, ListView, xm y+2 w620 r15 gSelectResult, #|Q1|Q2|Q3|Q4|Result|Max Delta|%A_Space%
Loop, % LV_GetCount("Column") - 1
   LV_ModifyCol(A_Index, "Integer")
Gui, Add, Button, xm wp gCalculate, Calculate
Gui, Add, StatusBar
Gui, Show, , Calculator
Return
; Exit ---------------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; Calculate the results ----------------------------------------------------------------------------------------------------------
Calculate:
Gui, +OwnDialogs
Gui, Submit, NoHide
;
Num := Amount
Min := Num + MinD
Max := Num + MaxD
MaxLoopCount := UDI
MaxResults := UDR
MaxDelta := UDD * 48
;
Q := Floor(Num // (P1 + P2 + P3 + P4))
Q -= Mod(Q, 48)
If (Q < MaxDelta) {
   MsgBox, 16, %A_ThisLabel%, Cannot iterate %UDI% times!
   GuiControl, Focus, UDI
   Return
}
LV_Delete()
;
Results := []
Loop {
   Q1 := Q2 := Q3 := Q4 := Q
   S1 := Q1 * P1
   Loop {
      S2 := S1 + (Q2 * P2)
      If (S2 >= Min)
         Break
      Q3 := Q
      Loop {
         S3 := S2 + (Q3 * P3)
         If (S3 >= Min)
            Break
         Q4 := Q
         Loop {
            S4 := S3 + (Q4 * P4)
            If (S4 >= Min) {
               If (S4 <= Max) {
                  R := (Q1 * P1) + (Q2 * P2) + (Q3 * P3) + (Q4 * P4)
                  D := 0
                  If ((Q2 - Q) > D)
                     D := Q2 - Q
                  If ((Q3 - Q) > D)
                     D := Q3 - Q
                  If ((Q4 - Q) > D)
                     D := Q4 - Q
                  If (D <= MaxDelta)
                     Results.Push([Q1, Q2, Q3, Q4, Round(R, 2), D])
                  If !(Results.Length() < MaxResults)
                     Break, 4
               }
               Break
            }
            Q4 += 48
         }
         Q3 += 48
      }
      Q2 += 48
   }
   Q -= 48
} Until (A_Index >= MaxLoopCount)
;
For I, R In Results
   LV_Add("", A_Index, R*)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
LV_ModifyCol(7, "Sort")
L := Results.Length()
SB_SetText("   Found " . L . " solution" . (L <> 1 ? "s." : "."))
Return
; Select a result from the ListView by double click
SelectResult:
Gui, +OwnDialogs
If (A_GuiEvent = "DoubleClick") && (SelectedRow := LV_GetNext()) {
   LV_GetText(Q1, SelectedRow, 2)
   LV_GetText(Q2, SelectedRow, 3)
   LV_GetText(Q3, SelectedRow, 4)
   LV_GetText(Q4, SelectedRow, 5)
   LV_GetText(R, SelectedRow, 6)
   ; do what you want to do with the variables here
   MsgBox, 0, Selected Result, %Q1% %Q2% %Q3% %Q4% %R% ; just for testing
}
Return
Thanks @Just me works like a charm, anyway, possible to single click to "selected"?
User avatar
ivill
Posts: 124
Joined: 13 May 2016, 02:23

Re: Split specified number into parts and sum

26 Feb 2018, 04:00

just me wrote:Well, I added a g-Label for the ListView. You can select a result by double click.

Code: Select all

#NoEnv
SetBatchLines, -1
; Constant multipliers -----------------------------------------------------------------------------------------------------------
P1 := 7.25
P2 := 6.53
P3 := 6.16
P4 := 5.43
; GUI ----------------------------------------------------------------------------------------------------------------------------
Gui, Margin, 10, 10
Gui, Add, Text, xm ym w200, Amount:
Gui, Add, Edit, xp y+2 wp Number vAmount, 30000
Gui, Add, Text, ym wp, Minimum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMinD, 10
Gui, Add, Text, ym wp, Maximum Deviation:
Gui, Add, Edit, xp y+2 wp Number vMaxD, 50
Gui, Add, Text, xm wp Section, Maximum Iterations:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDI Range1-3, 3
Gui, Add, Text, ys, Maximum Results:
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 15
Gui, Add, UpDown, vUDR Range1-30, 15
Gui, Add, Text, ys, Maximum Delta (n * 48):
Gui, Add, Edit, xp y+2 w200 ReadOnly Number, 3
Gui, Add, UpDown, vUDD Range1-5, 3
Gui, Add, Text, xm, Results:
Gui, Add, ListView, xm y+2 w620 r15 gSelectResult, #|Q1|Q2|Q3|Q4|Result|Max Delta|%A_Space%
Loop, % LV_GetCount("Column") - 1
   LV_ModifyCol(A_Index, "Integer")
Gui, Add, Button, xm wp gCalculate, Calculate
Gui, Add, StatusBar
Gui, Show, , Calculator
Return
; Exit ---------------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; Calculate the results ----------------------------------------------------------------------------------------------------------
Calculate:
Gui, +OwnDialogs
Gui, Submit, NoHide
;
Num := Amount
Min := Num + MinD
Max := Num + MaxD
MaxLoopCount := UDI
MaxResults := UDR
MaxDelta := UDD * 48
;
Q := Floor(Num // (P1 + P2 + P3 + P4))
Q -= Mod(Q, 48)
If (Q < MaxDelta) {
   MsgBox, 16, %A_ThisLabel%, Cannot iterate %UDI% times!
   GuiControl, Focus, UDI
   Return
}
LV_Delete()
;
Results := []
Loop {
   Q1 := Q2 := Q3 := Q4 := Q
   S1 := Q1 * P1
   Loop {
      S2 := S1 + (Q2 * P2)
      If (S2 >= Min)
         Break
      Q3 := Q
      Loop {
         S3 := S2 + (Q3 * P3)
         If (S3 >= Min)
            Break
         Q4 := Q
         Loop {
            S4 := S3 + (Q4 * P4)
            If (S4 >= Min) {
               If (S4 <= Max) {
                  R := (Q1 * P1) + (Q2 * P2) + (Q3 * P3) + (Q4 * P4)
                  D := 0
                  If ((Q2 - Q) > D)
                     D := Q2 - Q
                  If ((Q3 - Q) > D)
                     D := Q3 - Q
                  If ((Q4 - Q) > D)
                     D := Q4 - Q
                  If (D <= MaxDelta)
                     Results.Push([Q1, Q2, Q3, Q4, Round(R, 2), D])
                  If !(Results.Length() < MaxResults)
                     Break, 4
               }
               Break
            }
            Q4 += 48
         }
         Q3 += 48
      }
      Q2 += 48
   }
   Q -= 48
} Until (A_Index >= MaxLoopCount)
;
For I, R In Results
   LV_Add("", A_Index, R*)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
LV_ModifyCol(7, "Sort")
L := Results.Length()
SB_SetText("   Found " . L . " solution" . (L <> 1 ? "s." : "."))
Return
; Select a result from the ListView by double click
SelectResult:
Gui, +OwnDialogs
If (A_GuiEvent = "DoubleClick") && (SelectedRow := LV_GetNext()) {
   LV_GetText(Q1, SelectedRow, 2)
   LV_GetText(Q2, SelectedRow, 3)
   LV_GetText(Q3, SelectedRow, 4)
   LV_GetText(Q4, SelectedRow, 5)
   LV_GetText(R, SelectedRow, 6)
   ; do what you want to do with the variables here
   MsgBox, 0, Selected Result, %Q1% %Q2% %Q3% %Q4% %R% ; just for testing
}
Return
Hi, @just me, your script works very well, but i just got an idea and meet a challenge, can't accomplish it by myself:
How can i make the script works without a GUI, use a preset conditions and vAmount(for example 30000) to calculate then instant get the results MsgBox, %Q1% %Q2% %Q3% %Q4% %R% by default

Really appreciate for your great help

P.S. Started a new post : LV_GetText without a ListView/GUI

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bing [Bot], LAPIII, peter_ahk and 335 guests