Using if statements [= how to confirm a list of values is correct]

Hello, so I am creating a simple puzzle like application for school. https://airy-furrow-81.tiddlyhost.com/ Find testPuzzle1 and you should find the tiddler I am referring too. I want to have an if statement that basically checks when the correct cell has the correct tiddler inside. The mini tiddlers are number 1-25. I will note that $:/data/TiddlerGrid/alphaPuzzle/1/1 for example is a tiddler, and is referring specifically to the first cell in the forst xoloumn and first row (or it might be other way around, but my point still stands.) When opened, whichever tiddler isin that cell, the name of it pops up, so if the image tiddler titled 1 is there, it will show 1 in the text. I want to basically have a very long if statement that checks for each cell for the right image inside. Disregard the bottom tiddler, as it’s my fallback of having a guide to help to know if you’re correct. I have messed with if else widgets and tiddlywikis own built in versions and have had no luck.

It is difficult to reverse engineer your problem from your example.

I suggest making a simple and minimal example separate from your overall code the demonstrates your problem. Break it down into its smallest piece that demonstrates the probelm.

Like @TW_Tones, I find myself thinking:

  • I see your task (have a way of confirming “success” at solving).
  • I see you want to accomplish that task by using a long “if” structure.

But… Why are you attached to that approach? I can think of many other ways of solving your initial problem. Which one is best depends on your larger project.

For example, do you want to be able to generate other puzzle variations on the fly, with different dimensions and/or multiple solutions — and have your “solved yet?” algorithm effortlessly copy over? Do you need to make your solution-checker resistant to easy “cheating” by an end-user? Do you need some event to happen (a “SOLVED!” alert pops up), or do you just need text to conditionally show up, right there in the tiddler, exactly when all the squares are correctly set up?

I will also comment that so far, your puzzle wiki doesn’t really use tags and fields very effectively. For example, you have a bunch of tiddlers that fit the filter condition [prefix[$:/data/TiddlerGrid/alphaPuzzle]] (like the one you name in your OP). But these have nothing in common except the name-space — and that name-space includes apparently-experimental tiddlers that are not actually useful parts of your puzzle (at least, their role is different from being one of the 25 place-holding tiddlers). Gathering that batch of 25 place-holder tiddlers under a shared tag would make them much easier to work with as a set.

Fields (and tags, which really are a special kind of field) can be very helpful in making your task simpler, easier to troubleshoot, and easier to modify or extend to new cases. It looks like you started to attempt to make a “key” field…? (Is that what the field hey is trying to do on the tiddler named $:/data/TiddlerGrid/alphaPuzzle/1/1? That would be a good start.

(If it were my task, I’d build a filter that starts by looking for the 25 puzzle “position” tiddlers that currently share nothing other than that system namespace — and ensure than they each have a key field with the solution value. Then just have the filter COUNT those where the key field does NOT match the contents of the text field. When the count is zero, the puzzle is solved.)

I do hope that this isn’t a classwork assignment where your actual assigned task was to start from the puzzle — as set up by @inmysocks — and then to figure out on your own how to test for when the puzzle is solved… :wink: :thinking: :zipper_mouth_face:

1 Like

Although yes it’s a class assignment, my professor encourgaed me to ask TalkTW to find solutions. He’s very big on asking for help to learn.

Why I want to do an if statement is I mjyself am a programmer, but understanding the tiddlywiki syntax and layout has been very difficult for me as it seems tiddlywiki does what other traditional languages I already have learned very differently to the point it’s hard to understand how simple things like variables and arrays things like those work, so I am trying to find ways to get tiddlywiki to work in ways that I understand from say a C/Java/C++ perspective (the languages I do know well)

I tried using tags and fields, but again, I am not sure how those can be used. I understand an how an if statement would work in this case, and that if I can check each cell to see if the right image tiddler is there, I’d be golden.

I would just want there to be a line of text that says Incorrect/Not solved, and when it is solved, say correct.

I will try and use the method you proposed with the filter, but I am not sure how far i will get

If there are better solutions I would love to hear them, I am just not guaranteed to really understand them if the resources aren’t there.

Let’s start here. First, you want to be sure that your wiki “has” the information about which image is “right” — that is, which number belongs in which cell. You need to hold that information in a way that is easy to access and evaluate.

The best way to do that is to use a field, such as key, in each of the 25 tiddlers that represent cells (positions in the grid).

Maybe that’s what you (or someone else) started to do here, though the field is labeled “hey” — which looks like a simple typo to me:

Below I offer a first little tutorial. Take all of this code below… (There’s a “copy” button at upper right of the code block) … and paste it into a new tiddler in your wiki. (Alternatively, download the json attached here, which is a bit less well edited than code block below, and import it. improved_puzzle_tutorial.json (1.5 KB))

Once you create/import this tiddler, you can study its overview in view mode (and toggle back into edit to get a better sense of how it works)… this should get you oriented to some of the tools you need!

Here's a window into comparing `text` field and `key` field for each of the 25 system tiddlers that build the grid behind [[testPuzzle 1]]:

<$list filter="[prefix[$:/data/TiddlerGrid/alphaPuzzle/]]  :filter[has[text]get[title]length[]compare:integer:lt[36]]" counter="counter">

<!-- We’re looking for titles in this namespace... Filtering down to those with title length less than 36 — as one simple way to weed out some of the other titles in that namespace, which all happen to be longer. (The 25 cell-position tiddlers haven’t yet got a tag, or any or user-friendly handle, for gathering them neatly together as a set.) -->

<hr>

Cell # <<counter>>. Let's look at <$link/>

<!-- For each cell found in this filter list, we're going to peek into it. -->

: `text` field contains: ''{{!!text}}'' 

: `key` field contains <$edit-text tiddler=<<currentTiddler>> field="key" size="4"/>

<$let key={{!!key}}>

:Let’s compare ''{{!!text}}'' to ''<$text text={{{ [<currentTiddler>get[key]else[... Oh no this cell has no key!]] }}}/>''

<!-- Naming a variable to hold contents of the key field makes comparison more straightforward -->

Comparison result is... : <mark><$text text={{{ [<currentTiddler>get[text]match<key>then[yes!]else[nope]] }}}/></mark>

<!-- The triple-curly-braces `{{{` ... `}}}` give us a quick way to show the results of a filter. In this case, we don't want to return a link or list of links; we just want the result as plain text. -->

</$let>

</$list>

(NOTE for @choakly and others replying here: I notice the existing puzzle example wiki https://airy-furrow-81.tiddlyhost.com/ is in TW v5.2.1, so it currently is not equipped to handle the conditional shortcut syntax that has recently given us more familiar/intuitive if-then syntax in TiddlyWiki.)

Hello, just getting back to this, I love this solution. I don’t exactly know how the code is coding here, but I get the idea that its comparing the text (the names of the tiddlers) to the key fields. I just havew to go through and add those key fields.

Hello, so something with this, is there any possible way of getting the results to be used for something like if they’re all yes, it’ll say “you win!” or something along those lines? My only thought is a variable being used and when it equals 25 it’ll print show you win.

is the <$let key={{!!key}}> line create a variable, or does it allow you to edit a field value with code

You don’t need to set a variable at all.

Just use a filter to catch all the grid-position tiddlers where key and text fields DON’T match.

If there aren’t any of these, the puzzle is solved!

Approaching your task by looking for zero errors (rather than trying to count up to 25 correct answers) will generalize better when you adapt your solution for a 9-square or 16-square grid, or any other matching game.

HOW TO FIND where text and key fields don’t match:

START with that initial list of 25 grid-position tiddlers (which I gerrymandered, earlier in this thread, by looking for a prefix and then setting a length-limit, since there’s no unifying tag yet for these tiddlers)…

Once you have that list, you want to further FILTER it down to look — only among these 25 — for any tiddlers where the text field does NOT match the key field.

Fields can be referenced with {!!this-syntax} — so {!!key} (when it occurs in a filter) and {!!text} are the bits that will point to the fields you want to compare. Do these two fields match?

:filter[{!!text}match{!!key}] will show you the subset of tiddlers where they DO match…

But I’ve suggested looking for the tiddlers where they DON’T match. :thinking:

In TiddlyWiki filter syntax, an exclamation point before an operator such as match serves as an inverter or negation.

So the crucial filter expression is:

:filter[{!!text}!match{!!key}]

Either there will be a list at this point (of grid-square tiddlers where what’s there in text field does not match the key), or the list is empty (=no tiddlers fit these conditions).

The then operator and else operator capture the logic of “is there something here? If so, then show me THIS / Otherwise (else), show me THAT”.

So, here’s the skeleton I’m encouraging you to study:

{{{
INSERT YOUR BASIC EXISTING FILTER HERE AND APPEND...

:filter[{!!text}!match{!!key}] 
+[limit[1]] +[then[not yet solved]] 
+[else[SOLVED!]]
}}}

The triple-curly braces around the filter expression here are shorthand for: Just show me the results of this filter!

For troubleshooting purposes, you can remove the +[limit[1]] +[then[not yet solved]] bit, to see the list of incorrect squares.

The version I outline, above, suppresses that actual list of squares that don’t match. After all, you don’t want to telegraph — to your visiting player of the puzzle — exactly which squares are still incorrect!

The +[limit[1]] +[then[not yet solved]] sequence takes the list of incorrect grid-square tiddlers as input, ignores all but the first one, and then converts that title into a single not-yet-solved message (no need to repeat the message for each incorect square!). [then[xyz]] is a way to display a certain result for any non-empty value that reaches that point in the filter.

NEATENING UP:

By default, {{{ [all[filter results]] }}} will appear as a title list of links. That’s a bit odd for the “SOLVED!” or “not yet solved” messages. If you want to suppress those links (to “missing” tiddlers with those names), take that triple-curly-braced filter expression and make it the content of a <$text> widget.

If you omit the unsolved message, then you can easily put all sorts of celebratory styling around the solved message:

FANCIER STUFF:

If you want totally different styling for the not-yet-solved and SOLVED! message, you could have two different <$list> widget filters — one checking for the not-yet condition, and another checking for the solved condition. Then include whatever HTML and/or CSS you want for each message between the opening <$list filter="[blah[blah]]"> and the closing <$/list>.

(Recent TiddlyWiki updates include conditional shortcut syntax that makes it easier to build intuitive if/else decision trees.)

For the “SOLVED!” message, of course, you could build something much fancier. For example, you could have an alert that jumps up exactly at the moment the solving move is made. That requires tinkering with the actions triggered by each drag interaction, adding a step that checks whether the puzzle is solved, and triggers a new event as needed. The approach outlined above is a passive one; this filter is simply always running, and refreshing as needed when input values change.

1 Like

Didn’t see that you replied, biut thank you! I am still a bit confused on where in this it’s supposed to go, and whether i replace the original filter with this or adding it somewhere. Replacing this will show just one nope that doesn’t change. I understand what is happening, I am just not sure where it’s supposed to go in the code.

You can make a new tiddler with the filter-based “SOLVED!” message, or you can choose a place to insert the string I’ve been helping you build (the string starting with {{{ [prefix[... and ending with else[SOLVED!] }}}. Perhaps you want it in the puzzle tiddler, above or below the puzzle, so that it’s right there where the visitor is playing the puzzle. You can hard-code it there, or you can do the work in another tiddler called $:/alphaPuzzel/solved? (or whatever you want to call it), and then transclude that tiddler in the main puzzle interface ( {{$:/alphaPuzzel/solved?}})

The crucial thing is that my most recent post is giving only the “given this of squares, are there any unsolved ones?” step — it’s getting you from your list of grid-position tiddlers to the result message (SOLVED! or “not yet solved…” — or whatever kind of message(s) you want to display).

The first step was shared with you in the earlier post, which was a tutorial on how to bring these 25 tiddlers into focus, and easily ensure that each one has a key field that can hold the desired value. That earlier “tutorial” code took the form of a big LIST:

<$list filter="[prefix[$:/data/TiddlerGrid/alphaPuzzle/]]  :filter[has[text]get[title]length[]compare:integer:lt[36]]" counter="counter">

The filter part of that (effectively saying “cast a net around the 25 grid-position tiddlers”) is the part between quote marks in the list-widget code above:

[prefix[$:/data/TiddlerGrid/alphaPuzzle/]]  :filter[has[text]get[title]length[]compare:integer:lt[36]]

In the earlier tutorial, I built that filter to help you to peek into each of those 25 tiddlers and see what’s going on with the key field and text field for each one. (You could have done that work without a list widget — you could have just tracked each those 25 tiddlers down! But it would have taken a while and would have been a nuisance!) You need a <$list> widget if you want to automatically repeat a certain pattern of access for each tiddler within a set…

But for today’s task you’re not doing that kind of deep dive; you want “the bottom line”. That is, wherever you want to display the “solved” message, you’re not trying to display or interact with those 25 tiddlers, but just using that same initial filter to bring that set of 25 tiddlers into a kind of computational workspace, and then use further filter steps to “boil it down” to a smaller list of tiddlers (leaving only the ones for squares that don’t match the key). Based on that smaller list, you want to conditionally show something depending on whether that list boils down to something (mismatches still remaining), or to nothing (puzzle solved).

So, you don’t need the list widget. You just need something with this structure:

{{{

(1) filter that gets you the 25 grid-position tiddlers 
(starting with $:/data/TiddlerGrid/alphaPuzzle/ 
but excluding the long ones)

(2) the additional filter steps that take you 
*from* that list of 25 tiddlers *to* the conditional message

}}}

I hope both (1) and (2) are clearly in view at this point!


On a different note, I see that your recent `Puzzle Check 1’ tiddler (which you helpfully realized you could transclude within the main puzzle display tiddler!) is failing to yield accurate results. This is because it was trying to compare to each square’s key variable without being within the scope of where the key variable was defined.

But I should apologize, because setting a variable for the key field was not even necessary!

Inside the list (the kind of thing you’re doing with Puzzle Check 1), the micro-test, for each tiddler, can be much more elegant:

Cell # <<counter>>: <$text text={{{ [{!!key}match{!!text}then[yes!]else[nope]] }}}/>

I see, I got it working! I feel bad as you made that nice looking grid (PuzzleCheck), but it was a good tutorial on how to use fields effectively. I basically just hardcoded that solved line, my issue was syntax. Thank you very much for the help, my professor was glad to see an internet stranger at work helping one of his students, I was lost but I have a good understanding on this now.

Excellent!

And just for the record, I did enjoy — and solve — the puzzle! :wink:

Of course, you now want to make sure that clearing the puzzle isn’t going to erase your key fields, since that button seems currently designed to remove all those tiddlers including their key fields. But making sure that all the elements of the site play nicely with each other is a different can of worms. :slight_smile:

3 Likes