go to post Stuart Strickland · May 4, 2022 /// using first string replace with null each 'same' character found in second string leaving null or spacesClassMethod Detector(a As %String, b As %String) As %Boolean{q $$r(a,b)_$$r(b,a)?." "r(x,y) f s x=$replace(x,$e(y),"",,1,1),$e(y)="" ret:y="" x}/// 88 chars
go to post Stuart Strickland · Apr 8, 2022 I'm a fan of beyond compare but it is not always available on some of the sites I log in to. I'm not a fan of RCMP. I've got a Diff program that works in a terminal session that I use when I log on to a Cache version 5 site. Feel free to take this and do what you want with it (.MAC routines can be found on ^rMAC): Code ZRDIFF(Master="",Minor="",N1="",N2="",Show=1,Debug=0,Diffs=0,LengthWidth="40;160",UDL=0) ; Poor man's side by side diff ; Knocked up to run a quick diff on an old Caché version 5 system where my nice diff program won't work ; Usage: ; Pass in 1st routine (arg1 is Master) to compare against itself (in another namespace) or against 2nd routine (arg2 is Minor) ; N1 and N2 are optional namespaces ; Alternatively, pass in a pair of arrays to compare in Master and Minor but ensure top node is populated with something. ; To compare classes use ##class(%Compiler.UDL.TextServices).GetTextAsArray(,ClassName,.Array) and do your own thing. ; Call it like $$^ZRDIFF(Routine1,Routine2,Namespace1,Namespace2,0,0,.Diffs) to get it to return a non-zero number indicating there's a difference ; Make Routine1 and Routine2 variables and pass by reference to get back the 2 routines as arrays ; The lines of code that are the same will be lined up ; Show=1 to display to terminal ; ScreenLength and width can be passed in if your terminal doesn't go to 160 columns. ; Pass in "24;80" if you like, it will work. ; Pass in "24;9999" if you are going to use the arrays and pass them to something else that looks after formatting ; I Master="" Q:$Q "99No routine supplied" Q I Minor="" M Minor=Master ; ; To compare across namespaces populate N1 and N2 with a valid namespace ; default is current namespace I N1="" S N1=$ZNSPACE I N2="" S N2=$ZNSPACE ; ; Written to run on a putty terminal so screen handling is a bit noddy ; Don't like the screen handling? You change it. ; Look for InverseOn and InverseOff as they are the variables used for highlighting differences ; THIS IS FOR A VT100 EMULATION I Show W $C(27)_"[8;"_LengthWidth_"t" ; screen length(40) and width(160) N HalfWidth,I,L,Left,R,Right,MASTER,MINOR,MI,RA,RB,R1,R2 S HalfWidth=$P(LengthWidth,";",2)\2 ; ; Plan: ; Get 2 routines and normalise each line of code into 2 arrays so that ; all tab characters converted to spaces ; start of line is spaced out to 9 spaces (allows an 8 char tag), longer tags left alone ; Decide which of the two routines has more lines (left or right) ; Use the larger routine as the master routine ; Find all the lines of code in the minor routine that are identical to master and align them to the master ; but don't change the order of the lines, expand the arrays instead so that the similar lines match up ; Then lines broken into 78 character chunks so that the compare can be done side by side on a 160 wide screen ; S RA=Master,RB=Minor M R1=Master,R2=Minor ; Obvsiously, not doing this if you passed in a pair of arrays I $D(R1)<10 K R1 M R1=^[N1]ROUTINE(RA,0) I $D(R2)<19 K R2 M R2=^[N2]ROUTINE(RB,0) I '$G(R1(0)) S R1(0)=$O(R1(""),-1) ; number of lines in routine I '$G(R2(0)) S R2(0)=$O(R2(""),-1) ; ; UDL means you passed in a class or two in UDL format so don't bother normalising it's already done ; If they are not, then don't pass UDL=1 ! I 'UDL { D Normalise(.R1) D Normalise(.R2) } I R2(0)>R1(0) { S MASTER="R2",MINOR="R1" D Compare(.R2,.R1) } Else { S MASTER="R1",MINOR="R2" D Compare(.R1,.R2) } ; Getting the odd occurence where a pair of lines shows up next to each other claiming to be different when they are not ; Happens when ^ROUTINE has a missing line in the middle! ; so align them again S I=0 F { S I=$O(Master(I)) q:'I I Master(I)'="",$G(Minor(I))="" { ; they are the same I $G(Master(I-1))="",$G(Minor(I-1))=Master(I) S Minor(I)=Minor(I-1) K Master(I-1),Minor(I-1) continue I $G(Master(I+1))="",$G(Minor(I+1))=Master(I) S Minor(I)=Minor(I+1) K Master(I+1),Minor(I+1) continue } } I Show { S MI=0 W #!,$S(MASTER="R1":$$LJ($$LJ(N1,15)_RA,HalfWidth)_$$LJ(N2,15)_RB,1:$$LJ($$LJ(N2,15)_RB,HalfWidth)_$$LJ(N1,15)_RA) F { S MI=$O(Master(MI)) Q:'MI S Left=$S(MASTER="R1":Master(MI),1:Minor(MI)) S Right=$S(MASTER="R2":Master(MI),1:Minor(MI)) I Left'=Right,$I(Diffs) S Diffs(MI)="" ; lines where something is different ; Convert routine into lines less than 80 characters long F { S L=$E(Left,1,HalfWidth-2) S Left=$E(Left,HalfWidth-1,9999) S R=$E(Right,1,HalfWidth-2) S Right=$E(Right,HalfWidth-1,9999) D Show(L,R) q:Left_Right="" } } } ; Just in case you passed in arrays by reference and are expecting the left and right hand routines to come back to you... K Left,Right I MASTER="R1" { ; don't need to do anything - already the right way round } Else { M Left=Master,Right=Minor K Master,Minor M Master=Left,Minor=Right } S Master=RA,Minor=RB q:$Q Diffs q ; Normalise(ROU) N i,I,Line,N S i=0 F I=1:1:ROU(0) { S Line=$G(ROU(I)) ; need the $G because some old systems have missing lines of code! Don't ask me. ; swap tabs for spaces S Line=$TR(Line,$c(9)," ") ; if first character is a " " make it 9 spaces I $E(Line)=" " S $E(Line)=" " ; or if it's a tag with no arguments, pad it out to 9 spaces I $P(Line," ")?1(1"%",1AN).AN { S $P(Line," ")=$$LJ($P(Line," "),9) } // or if it has arguments and is (reasonable guess) less than 8 characters, pad out to 9 spaces, could fail if default values for arguments include spaces or braces ElseIf $L($P(Line,")"))<8,$P(Line," ")?1(1"%",1AN).AN1"(".e1") " { S $P(Line," ")=$$LJ($P(Line," "),9) } // leave everything else alone ; S N($i(i))=Line } ; Now the noralised routine is in N() move it to R1() or R2() S N(0)=ROU(0) K ROU M ROU=N Q R1LinesUpLater(I,i) ; parameter passed by value so will return to orignal value on quit N OK S OK=0 F { S I=$O(ROU1(I)) q:'I F { S i=$o(ROU2(i)) Q:'i ; NON-NUMERIC CATCHES THINGS LIKE "LANG" ; 2 consecutive lines the same will have to do I ROU1(I)=ROU2(i) { I ($G(ROU1(I+1))=$G(ROU2(i+1))) S OK=1 Q } } Q:OK!'i } Q OK R2LinesUpLater(I,i) ; parameter passed by value so will return to orignal value on quit N OK S OK=0 F { S i=$O(ROU2(i)) q:'i F { S I=$o(ROU1(I)) Q:'I ; NON-NUMERIC CATCHES THINGS LIKE "LANG" ; 2 consecutive lines the same will have to do I ROU1(I)=ROU2(i) { I ($G(ROU1(I+1))=$G(ROU2(i+1))) S OK=1 Q } } Q:OK!'I } Q OK ; left justify LJ(x,n) q x_$j("",n-$l(x)) ; Part(x,ION,IOFF) w:x'="" ION w x w:x'="" IOFF q "" Show(Left,Right) ; show the current row and also highlight when different N InverseOn,InverseOff S InverseOn=$s(Left=Right:"",1:$c(27,91)_"7m") S InverseOff=$s(Left=Right:"",1:$c(27,91)_"27m") W ! W $$Part(Left,InverseOn,InverseOff) W ?HalfWidth W $$Part(Right,InverseOn,InverseOff) q ; Compare(ROU1,ROU2) N I,i S (I,i,MI)=0 F { S I=$O(ROU1(I),1,L) Q:'I ; NON-NUMERIC CATCHES THINGS LIKE "LANG" F { S i=$o(ROU2(i),1,R) Q:'i ; NON-NUMERIC CATCHES THINGS LIKE "LANG" ; 2 consecutive lines the same will have to do I ROU1(I)=ROU2(i) { ; this works for the first line and last line I ($G(ROU1(I+1))=$G(ROU2(i+1))) || (I=i) || $$R1LinesUpLater(I,i+1) || $$R2LinesUpLater(I+1,i) { ; move to a new array and make them line up S MI=MI+1 S Master(MI)=ROU1(I),Minor(MI)=ROU2(i) D:$g(Debug) Show(Master(MI),Minor(MI)) Q ; go get next ROU1(I) } ; still here? ; Then 2 lines the same but next lines are not and ROU1(I+1) doesn't have a matching line later in ROU2(i+1 onwards) ; Move ROU1(I+1) to Master and increment I S MI=MI+1 S Master(MI)=ROU1(I),Minor(MI)=ROU2(i) D:$g(Debug) Show(Master(MI),Minor(MI)) q ;S MI=MI+1,I=I+1,i=i-1 ; was nearly working but Quit works better I I'>ROU1(0) { S Master(MI)=ROU1(I),Minor(MI)="" D:$g(Debug) Show(Master(MI),Minor(MI)) } Q } ; got here then they are different ; if they line up later then show the line from ROU2 now I $$R1LinesUpLater(I,i+1) { S MI=MI+1 S Master(MI)="",Minor(MI)=ROU2(i) D:$g(Debug) Show(Master(MI),Minor(MI)) Q ; go get next ROU1(I) } ; if they line up later then show the line from ROU1 now I $$R2LinesUpLater(I,i-1) { S MI=MI+1,i=i-1 S Master(MI)=ROU1(I),Minor(MI)="" D:$g(Debug) Show(Master(MI),Minor(MI)) Q ; go get next ROU1(I) } ; Still here? ; Then 2 different lines, show them both S MI=MI+1 S Master(MI)=ROU1(I),Minor(MI)="" D:$g(Debug) Show(Master(MI),Minor(MI)) S MI=MI+1 S Master(MI)="",Minor(MI)=ROU2(i) D:$g(Debug) Show(Master(MI),Minor(MI)) Q } } q ; TEST k S r1="GT101",r2="GT101" D ZRDIFF(.r1,.r2,"APEX","TAPEX",1,0,.Diffs) Q
go to post Stuart Strickland · Mar 4, 2022 Impressive Robert! I'd never heard of proleptic calendars before. If I don't communicate again soon, happy new year in 28 days time.
go to post Stuart Strickland · Mar 4, 2022 Nice article. Didn't know the easy way round negative dates. But how does it handle the English calendar riots of 1752 when we went from September 2nd to September 14th overnight? It returns a value of -32438 for September 3rd 1752 which didn't exist in England which is where I am now. Someone needs to fix this quickly!
go to post Stuart Strickland · Feb 2, 2022 Add's to GJ's effort and counts how many occurrences of the odd integer to be able to return exact answer (not a $ZABS answer).
go to post Stuart Strickland · Feb 2, 2022 ClassMethod Solve(o As %String) As %Integer { s i=$l(o,","),j=$l(o,"-")-1,k=i-j-j s:k<0 k=k-j-j s m=$tr(o,",","+")_"/"_k q @m }
go to post Stuart Strickland · Dec 1, 2021 Thanks Robert. I guess that by now all the points worth gaining are gone so it won't hurt to post this. Is this the sort of answer that is being looked for? (Rename classname to Day1?, Entry point should be ClassMethod Test()?)
go to post Stuart Strickland · Dec 1, 2021 So it is a race. And being awake at the right time no matter where you are in the world is a big advantage given a fixed start time of Midnight UTC-5.
go to post Stuart Strickland · Dec 1, 2021 Thanks for the quick reply. Yep, worked first time on a MAC. Still not sure of the rules, and given your experience, I'm not sure it will be enjoyable. Can't believe this is the template: At least I've gained some knowledge on some of what can be done with Docker.
go to post Stuart Strickland · Dec 1, 2021 I was going to play but it is difficult to get started. Tried to get the template, downloaded git and Docker desktop, got a git account, got IRIS working through Docker - was quite impressed with that) but cannot get the template. Am getting at least 2 errors on "docker-compose build" command: Is it possible to play without the template? Surely it's just a class in UDL format? The day 1 problem is easy to solve. I expect most of us could do it in one line of code. But what are the rules? How does the scoring work? Is it a race? Do you need to be in the first 5 people to finish it every day? Is it judged by someone? If so, what are you looking for? If you can't get your entry in on day 1 will you be too far behind? Going to try it on a MAC instead of Windows, maybe that will help.
go to post Stuart Strickland · Sep 9, 2021 or include S X=$ZU(123,0,1,1) in your system startup routine so that the only date that ever shows up with a 2 digit year is 1st Jan 1841 Check out the old %DATE utility
go to post Stuart Strickland · Aug 26, 2021 Dang! Might have been interested at the higher end of that salary per month.
go to post Stuart Strickland · Aug 5, 2021 Or this BinaryToDecimal(Binary,Debug=0) i Debug { w !,"Binary number: ",Binary w !,"Bit",?20,"Cumulative",! } s Decimal=0 f Power=0:1 { s Bit=$e(Binary,*) ; last digit q:Bit="" ; at end s $e(Binary,*)="" ; shorten binary number by removing last character s Integer=(2**Power)*Bit ; 2**0 =1, 2**1 =2, 2**2 =4 etc.. s Decimal=Decimal+Integer ; running decimal sum of each Bit i Debug w Integer,?20,Decimal,! } q Decimal
go to post Stuart Strickland · Jul 23, 2021 Prefer the SET method for both readability and performance. However, when it comes to readability, I see it as my deficiency if I can't read it instead of the author's deficiency - unless the code is deliberately obtuse. And when it comes to performance, you should only write something unreadable if it is necessary to gain performance for code run hundreds of thousands of times a day. But then you would comment your code so well that anyone could read the comment and wouldn't need to read the code to know how it worked and what it does.
go to post Stuart Strickland · Jul 10, 2021 can save 4 more characters with $p("lfa7ravo7harlie7elta7cho7oxtrot7olf7otel7ndia7uliett7ilo7ima7ike7ovember7scar7apa7uebec7omeo7ierra7ango7niform7ictor7hiskey7ray7ankee7ulu",7,$a(c)#32) instead of 's l=' and '$p(l,'
go to post Stuart Strickland · Jul 9, 2021 N(i) s l="lfa7ravo7harlie7elta7cho7oxtrot7olf7otel7ndia7uliett7ilo7ima7ike7ovember7scar7apa7uebec7omeo7ierra7ango7niform7ictor7hiskey7ray7ankee7ulu" f j=1:1:$l(i) s c=$e(i,j),o=$g(o)_$s(",.!?"[c:c,c?1a:$e(" ",j>1)_c_$p(l,7,$a(c)#32),1:"") q o ; 243 chars ; save 2 quote characters by using a number (7) as the delimiter ; save characters by not $ZCVT to upper, $A(k)#32 works fine for lower and upper ;save on $ZSTRIP of whitespace by only adding space character for every letter after 1st one ; ensure to follow the rules on allowed punctuation and exclude all other characters
go to post Stuart Strickland · May 20, 2021 Hi Oliver, I spent 20 years developing software, originally in MUMPS but now in Objectscript, runs on IRIS, that generates SWIFT MT messages for transmission in categories 1,2,3 and 5. Also receives messages in all categories and decodes and processes them. System also handles message matching and bank reconciliations. All automated save for a bit of exception handling when the wrong data is input. Also seamless connectivity with SWIFT Alliance system so the messages go straight out from the back office system and across the SWIFT network with full ACK/NACK processing. Added GPI and LAU to the connectivity process. Did a bit of freelance work a couple of years ago on the MX messages too. Processed about 4 billion messages in 20 years with close to 100% STP. It's all quite do-able in IRIS.