Random Text from a list of 10 or so choices

@gglick

I would like to ask both of you,
instead of choosing text randomly, can we make macro to choose text one after the other.

I mean, first time I run macro, it should choose first line of text from the list. Second time I run macro, it should choose second line of text from the list. and so on

I also have asked same question here

There are lots and lots of ways to do this in Keyboard Maestro. But the key is understanding that after each Macro run one thing that can persist (and provide a count of how many times you have run the Macro) is a Global Variable.

So, you make a Global Variable of "1" and the first time the Macro is run it adds "1" to that, making the Variable "2". And the next time you run the Macro is adds another "1" making the Variable "3" etc. This is the way the Macro knows how many times it has run and can choose which bit of text to display/use. Once you reach the total of however many pieces of text you have the Variable is reset to "1" and the cycle can start again.

Here is an example, to show the concept.

(It is just an example as I do not know what form your original "lines" of data are. Whatever they are, there will be a way for Keyboard Maestro to get at each line and cycle them on each Macro run.)

EXAMPLE Cycle through list on each Macro run.kmmacros (11.0 KB)

Click to Show Image of Macro

2 Likes

Thank you so much.
Let me try this out.

Hey I tried but 'Set variable __ to calculation __' is giving me error. See the text color changed from white to orange in the screenshot

Here is a screenshot of error msg as well:
Screen Shot 2022-10-25 at 16.27.05

The orange colour is because at this point in writing the Macro, ytintro_counter doesn't exist. But on first run the Macro should create ytintro_counter.

I have tried it on my Mac and it works.

(The top of your screenshot is not showing all the conditions for the If Then. It should be set so that "any" of the following are true, not "all".)

1 Like

Thanks for the prompt reply. That really saves from getting discouraged.

Thanks for letting me know. While I was exploring, I went ahead into setting and put the value as '1' for ytintrol_counter, which was earlier showing as 'default value'.
And that worked.

And all the credit goes to you. Thank you.

1 Like

@Arturito Can you post the solution you came up with? I am looking to do the same thing. I will go through @JMichaelTX and make those modifications as well but nice to see a finished product from a thread post.

For some reason this is not very random for me at all and favors the last line in a line of fifty options. Out of 20 runs it chose 18 times the last line of text.

Thank you for this, this macro is much more random.

I like your alternative.

shuf -n 1 l

For what it is worth the shuf command is optimized for this purpose and avoids sorting the entire file, making it faster for large files.

"shuf" is not built-in to macOS.

My bad.

This works pretty fast with a list of 50, so no need really for that command anyway.

Random Text.kmmacros (32 KB)

sort -R | head -n 1

Here's an advanced tip... be aware that duplicate lines don't increase the chance that that line is taken. For example, this code will have a 50% chance of producing "1" and 50% of producing "2"...

image

This is because the sort command makes its decision based on unique lines. Or more accurately, unique keys, which by default the sort command determines on a full-line basis.

A couple of years ago I thought I could increase the chance of a value being picked by increasing the number of times that the line occurred in the input text, and I discovered this issue at that time. I solved the problem by adding some random characters to each line.

1 Like

Also for what it's worth -- KM has changed a bit since many of the posts above were made. And a big change was the ability to use \n as a custom array delimiter.

So to display a random line from the variable Local_lines it's as simple as:

image

%Variable%Local_lines[RAND(1,LINES(%Variable%Local_lines%))]\n%

Demo: Random Line.kmmacros (2.6 KB)

1 Like

That's cool. I figured something had changed I wasn't able to get this to work. I love all the options.

That's a bug, it is using Line instead of Result at the end of the macro.

1 Like

For what it's worth, the Modern Syntax option of Keyboard Maestro 11 allows for a simplification of the JavaScript version:

const randomRInt = (low, high) =>
    low + Math.floor(
        (Math.random() * ((high - low) + 1))
    );

const xs = kmvar.local_Source.split("\n");

return xs[randomRInt(0, xs.length - 1)];


Randomly chosen line of text (simplified for KM11+).kmmacros (2.5 KB)

1 Like

OK, here is a definitive, modern, way to do it in Keyboard Maestro. Assuming the variable Source contains the lines, separated by returns, then use this action:

image

%Variable%Source[1+RAND(CALCULATE(%Variable%Source[0]\n%))]\n%

(edit: 1+ added to correct the index to 1-based).

This uses several modern features of Keyboard Maestro:

  • Array indexing of Variables with a custom separator.
  • Variable Index of 0 returning the count of the entries in the array.
  • The CALCULATE function to process tokens within a calculation part.
3 Likes

I hesitate to mention this, but I think that should be:

%Variable%Local_lines[RAND(1,(CALCULATE(%Variable%Source[0]\n%)))]\n%

If I'm understanding correctly, RAND(N) has a one in N chance of returning 0 so you'll occasionally get the number of lines rather than a random line. Using RAND(1,N) will prevent that.

3 Likes

Another method, since RAND(N) includes 0 but not N, could be to simply add 1 to the random number (untested):

%Variable%Source[RAND(CALCULATE(%Variable%Source[0]\n%) + 1)]\n%
1 Like

I posted a finished version of this with modifications to start over once it has reached the end of the list at the link below.