Stuart Strickland · Mar 12, 2024 go to post

ClassMethod Type(args...) As %String
{
 // no attempt made at miniturizing the code, 362 chars not including comments
 res="Constant"
 i=1:1 {
  q:'$d(args(i)) w=$tr(args(i)," ")
  p=2:1:$l(w,",") {
   a=$l($p(w,",",p)),b=$l($p(w,",",p-1))
   s d=$s(a>b:1,a<b:-1,1:0)
   d>0 res=$case(res,"Constant":"Increasing","Increasing":"Increasing",:"Unsorted")
   d<0 res=$case(res,"Constant":"Decreasing","Decreasing":"Decreasing",:"Unsorted")
   }
  }
 res
}
 

Stuart Strickland · Nov 16, 2023 go to post

You need an interactive user's system to run this without any user interaction?

If it doesn't matter who runs it and it doesn't take any serious resources and could run unnoticed then could you set a global that is checked by some code that is regularly run by a group of users? The first interactive process that finds the global could do your $ZF for you? Say SET ^GLOBAL("RUN NOTEPAD")=$H

Then in the common piece of code L +^GLOBAL("RUN NOTEPAD"):0 I $T {S:$D(^GLOBAL("RUN NOTEPAD")) X=$ZF(-1,"C:\Windows\notepad.exe") K ^GLOBAL("RUN NOTEPAD") L -K ^GLOBAL("RUN NOTEPAD")}

Otherwise I think you need to fix the destination program so it will run in the background.

Stuart Strickland · Nov 10, 2023 go to post

Thanks Vitaliy! That is just what I was looking for!

I suppose that underneath the code, deep down in Quote^%qcr, it may be doing the same as I'm doing, but it is unlikely to have any errors in it and it's not a wild assumption that it will do it in the most efficient way.

Alas, the few version 5 sites will have to live with my slower code

%SYS>w $zv
Cache for UNIX (IBM PowerPC/32-bit) 5.0.18 (Build 6103 + Adhoc 3626) Tue Mar 7 2006 11:55:33 EST
%SYS>W $zcvt(##CLASS(%Library.Utility).FormatString($lb("abc","DEF","",,"tesT",$lb(0))),"u")

W $ZCVT(##CLASS(%Library.Utility).FormatString($LB("abc","DEF","",,"tesT",$LB(0)
^
)),"u")
<CLASS DOES NOT EXIST>
%SYS>W $zcvt(##CLASS(%Utility).FormatString($lb("abc","DEF","",,"tesT",$lb(0))),"u")

W $ZCVT(##CLASS(%Utility).FormatString($LB("abc","DEF","",,"tesT",$LB(0))),"u")
^
<CLASS DOES NOT EXIST>

Stuart Strickland · Nov 8, 2023 go to post

That's a really good idea. Doesn't quite get there because of nested lists.

Here is a bit more visual info on the problem:

>s x=$LB("test","for","searching unknown strings here is a very long piece with enough characters to get a lowercase alpha as a $list marker","items","in","lists",$lb("/subs","/values","nested list","did you see that ""w"" before the third piece?"))

>f i=1:1:$l(x) s c=$e(x,i) w:c?1c "$c("_$a(c)_")" w:c'?1c c

$c(6)$c(1)test$c(5)$c(1)forw$c(1)searching unknown strings here is a very long piece with enough characters to get a lowercase alpha as a $list marker$c(7)$c(1)items$c(4)$c(1)in$c(7)$c(1)listsM$c(1)$c(7)$c(1)/subs$c(9)$c(1)/values$c(13)$c(1)nested list.$c(1)did you see that "w" before the third piece?

It's those potential lowercase list separators that are forcing me to go the long way round with stepping through each piece. $ListToString may help speed the code up especially as I'm not really expecting deep nesting of lists.

Stuart Strickland · Nov 8, 2023 go to post

Thanks Dmitry

I want to find any string in another string that could be a plain string, a $LIST, or a series of nested $LIST to any depth - basically an unkown structure. The string I'm searching in can be any size and the pieces can be any size. And I wan't to do a case insensitive search through a large amount of data and I want instant results. And I want to know the character positions of what was found. And I want the results in a human readable format. And just to make it hard, it has to run on everything from Caché version 5 upwards which means $LISTNEXT, $LISTVALID are not always available.

Stuart Strickland · Nov 8, 2023 go to post

That would be fine if I was looking for the full element value as my search string. I'm looking for any occurance, full or part, in a lot of data.

 From the documentation:
  $LISTFIND searches the specified list for the first instance of the requested value. A match must be exact and consist of the full element value. Letter comparisons are case-sensitive. Numbers are compared in canonical form. If an exact match is found, $LISTFIND returns the position of the matching element. If value is not found, $LISTFIND returns a 0.

 // Suppose the string I'm  looking in is in
 S X=$LB("Stuart Strickland","Yaron Munz") // X could be anything
 // and I'm looking for "MUNZ"
 I $zcvt(X,"u")["MUNZ" Q 1  // I think this is quick but could cause a problem by converting lower case $LIST spacers to upper
 S sc=0 F i=1:1:$LL(X) S Y=$LG(X,i) I $zcvt(Y,"u")["MUNZ" s sc=1  // I think this is slow
 S sc=$LISTFIND(X,"MUNZ")         // I know this will not work
 S sc=$LISTFIND($zcvt(X),"MUNZ")  // I know this will not work and might even cause an error
 Q sc

Stuart Strickland · Oct 23, 2023 go to post

132

ClassMethod Calendar(As %Integer) As %String
{
$p("Metal7Water7Wood7Fire7Earth",7,y#10\2+1)_" "_$p("Monkey7Rooster7Dog7Pig7Rat7Ox7Tiger7Rabbit7Dragon7Snake7Horse7Goat",7,y#12+1)
}
 

Stuart Strickland · Aug 3, 2023 go to post

That article is an interesting read for anyone who has written code that goes directly to the generated INT code. I will need to re-think some of my older code that finds lines of code from $ZE and then displays and diagnoses the source of errors based on the variable names it finds there. I might also have to start using a mainstream debugger.

Stuart Strickland · Aug 2, 2023 go to post

Ah yes, $Change can save a character on $Replace. And nested $TR saves on $zstrip.

f{z=x,x=$change($tr(x,$tr(x,"()")),"()",9) ret:x=x=""}

Stuart Strickland · Aug 2, 2023 go to post

//57?

ClassMethod IsValid(s As %String) As %Boolean {

 q +$$zTestSearchString^%iFind.Utils.1($$$URLENCODE(s))

}

Stuart Strickland · Aug 1, 2023 go to post

You are correct. implementation.size sees $c(13,10) as the end of line character. I counted manually and added 1, not 2.

Stuart Strickland · Jul 28, 2023 go to post

61 bytes. Could an AI machine ever beat a human at code golf? Don't they just use brute force?

ClassMethod IsValid(x)
{
 f{z=x,x=$replace($tr(x,$tr(x,"()")),"()",9) ret:x=x=""}
}
 

Stuart Strickland · Jul 28, 2023 go to post

Class codeGolf.ParenthesisHell { ClassMethod IsValid(s As %String) As %Boolean

{

f{s t=s,s=$replace(s,"()","") ret:t=s s=""}

}

Stuart Strickland · Jul 14, 2023 go to post

I found a work around for it. Not perfect but it will do

S RTN=$ZU(96,9) // or $SYSTEM.Process.CallingRoutine() which is identical in this situation

RTN="" I=$ZU(41):-1:1 RTN=$P($ZU(41,I),"^",3) RTN'=$T(+0) Q:RTN'=""

Stuart Strickland · Jul 13, 2023 go to post

It appears to only work intermittently from "D zzpp".

If I ZLOAD another routine then go back and ZLOAD the first one, then it doesn't work.

But if I issue an argumentless ZSAVE  followed by "d zzpp" it works again.

Stuart Strickland · May 18, 2023 go to post
38, not good if the strings will never match

ClassMethod Rotations(a As %String, b As %String) As %Integer
{
 f i=0:1 ret:a=b i s b=$e(b,2,*)_$e(b)
}
Stuart Strickland · Apr 13, 2023 go to post

So much easier with journalling switched on!

In February 2000 we had to "undelete" a global containing all the cash transaction records at a large investment management institution when one of our colleagues accidentally deleted it near the end of the day. No journals, no backup, no option to re-input a whole day's work. Luckily the data was still there, albeit with no block pointers. It was a DSM system so we modified a program called ^BLCKDMP to read every block on the disk and write every node from our lost global out to an O/S file in %GO format. Took 15 hours to run and we had the system back by 9am the next day.

Needless to say, everything changed from then with regards to journalling and backups and programmer access.

It was an interesting experience in emergency firefighting and a nice learning experience in how the data is stored using the "common characters" space saving mechanism. M is really quite brilliant.

Stuart Strickland · Mar 19, 2023 go to post

I remember working on a system like that written in something called MaxiMumps. When doing their equivalent of $Order the second time you found null was the end of the subscript range.

They also had an post-conditional character ";" which behaved like "if not". These two lines were effectively the same.

S:A'=B C=D

S;A=B C=D

...to save a character! 

Stuart Strickland · Feb 19, 2023 go to post

Hi Mark,

When looping through numerics, unless you intervene, it will loop through every number in magnitude order until you reach the end. So, if you start at 8009 and 8010 exists then it will find it. And 8009 is not next to 800900001 by a long way.

When looping through strings, it's going to go through them like a human would when going through a dictionary. All words with the same prefix are next to each other. So you can easily stop your loop immediately when you find a word that doesn't match.

This code will probably do what you want, athough I haven't tested it:

Noddy ;; Find all subscripts with numeric prefix using minimum $ORDER
    ;
Find(Prefix=8009,MaxSubscriptlength=12)
    Prefix=+Prefix {
        // Must be numeric
        MatchLength=$l(Prefix)
        I=MatchLength:1:MaxSubscriptLength {
            // try starting from every number beginning with
            // 8009, thru 80090, 800900, up to say 800900000000
            // or whatever the maximum subscript length is
            Start=Prefix_$E("000000000000",0,I-MatchLength)
            F  {
                // see if we found one, even at the start of the loop
                $D(^REXREF3(1,Start)) {
                    // but it must have our prefix
                    // this test can end the loop!
                    Q:$E(Start,1,MatchLength)'=Prefix
                    // but only looking for numerics in this loop
                    // don't want to find again later
                    Q:Start'=+Start
                    // Now do whatever it is you want to do with it..
                    // <REMOVE MINE AND INSERT YOUR CODE HERE>
                    !,Start
                }
                Start=$O(^REXREF3(1,Start))
                Q:Start=""
            }
        }
    }
    // Now look for strings with that prefix
    // all strings starting with 8009 will immediately follow "8009 "
    // so start there, there won't be an numeric subscripts following a string
    Start=Prefix
    MatchLength=$l(Prefix)
    Prefix=+Prefix Start=Start_" "
    F  {
        // see if we found one, even at the start of the loop
        $D(^REXREF3(1,Start)) {
            // but it must have our prefix
            // this test can end the loop!
            Q:$E(Start,1,MatchLength)'=Prefix
            // Now do whatever it is you want to do with it..
            // <REMOVE MINE AND INSERT YOUR CODE HERE>
            !,Start
        }
        Start=$O(^REXREF3(1,Start))
        Q:Start=""
    }
    q