|
| 1 | += A PowerShell Solution |
| 2 | + |
| 3 | +English | xref:README.adoc[简体中文] |
| 4 | + |
| 5 | +PowerShell is the \#33 most used language in Github as of 2022 Q1 according to https://madnight.github.io/githut/#/pull_requests/2022/1[GitHut's statistics]. Let's take a look at what this scripting language can do. |
| 6 | + |
| 7 | +image:http://telegra.ph/file/cb631e2869a7540a84b87.png[screenshot] |
| 8 | + |
| 9 | +== Code |
| 10 | + |
| 11 | +3 alphanumericals chosen: `i`, `e` and `x`. |
| 12 | + |
| 13 | +[source,powershell] |
| 14 | +---- |
| 15 | +$i=$?+$? |
| 16 | +$e=$i+$i |
| 17 | +$xi=$x=$e+$i |
| 18 | +$xe=""+$x+$x |
| 19 | +$xx=""+$x+--$e |
| 20 | +$x=(""+$?)[$i] |
| 21 | +iex "`$ex=""``$x{$xe}"";`$xe=""``$x{$xx}""" |
| 22 | +$ii=$e+++$i |
| 23 | +$ix=$ii+$i |
| 24 | +$ei=$e*$i |
| 25 | +$x="``$x{" |
| 26 | +iex "`$e=""$x$e$ei}e$x$xi$xe}$x$xi$xe}$x$xi$ex}, $x$ii$ix}$x$xi$ex}$x$ix$i}$x$xi$xe}$x$xi$e}!""" |
| 27 | +$e |
| 28 | +---- |
| 29 | + |
| 30 | +Semicolons are necessary if the code is written in a single line. The two are equivalent. |
| 31 | + |
| 32 | +[source,powershell] |
| 33 | +---- |
| 34 | +$i=$?+$?;$e=$i+$i;$xi=$x=$e+$i;$xe=""+$x+$x;$xx=""+$x+--$e;$x=(""+$?)[$i];iex "`$ex=""``$x{$xe}"";`$xe=""``$x{$xx}""";$ii=$e+++$i;$ix=$ii+$i;$ei=$e*$i;$x="``$x{";iex "`$e=""$x$e$ei}e$x$xi$xe}$x$xi$xe}$x$xi$ex}, $x$ii$ix}$x$xi$ex}$x$ix$i}$x$xi$xe}$x$xi$e}!""";$e |
| 35 | +---- |
| 36 | + |
| 37 | +=== Environment |
| 38 | + |
| 39 | +*PowerShell 7.2.5* |
| 40 | + |
| 41 | +Please install it manually. Since the code uses the `"`u{x}"` syntax which was added in PowerShell 6.0, it won't work on the one preinstalled on Windows. |
| 42 | + |
| 43 | +The code can be run by either pasting it into the PowerShell console or using `.\x.ps1`. |
| 44 | + |
| 45 | +== Explanation |
| 46 | + |
| 47 | +My first thought was if it is possible to directly add or subtract the ASCII value of chars like in most C-style language. However, this is not possible. The target type must be written when it comes to explicit type conversion. `[char]65` does give us the character `A`, but there are 4 different letters. And if we want to get a number, it's `[int] something`. footnote:[https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/converting-ascii-and-characters[Converting ASCII and Characters - Power Tips - Power Tips - IDERA Community]]. |
| 48 | + |
| 49 | +=== Selection of the 3 characters |
| 50 | + |
| 51 | +Then I try to find the eval function. First I found the very one `Invoke-Expression`, but that is too long. Most PowerShell commands are long. That's bad for a scripting language. Then I found that the ampersand, `&`, can execute command in a string. But it works on a single _command_, without parameters.footnote:[https://stackoverflow.com/questions/50018274/why-does-invoke-operator-and-invoke-expression-produce-different-results-for[Why does invoke operator (&) and Invoke-Expression produce different results for the same input? - Stack Overflow]] Luckily, there is an alias of `Invoke-Expression`: `iex`. |
| 52 | + |
| 53 | +=== The first digit |
| 54 | + |
| 55 | +Since there is no way to turn a single char into another, the only way to get a 4th character is to split a String elsewhere. In PowerShell, a character quoted by either `''` or `"` is always a string, an array of chars. There is no .pop() in Powershell,footnote:[https://stackoverflow.com/questions/24754822/powershell-remove-item-0-from-an-array[PowerShell Remove item 0 from an array - Stack Overflow]] so we need to access it by index if we want a specific character. |
| 56 | + |
| 57 | +[source,powershell] |
| 58 | +---- |
| 59 | +$i = $? + $? |
| 60 | +---- |
| 61 | + |
| 62 | +- $? contains the execution status of the last command. It is `True` initially or when the last command succeeded.footnote:[https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.2#section-1[$? - PowerShell Core - About - Automatic Variables]] |
| 63 | + |
| 64 | +- The equivalent of `==` is `-eq` in Powershell; `$i==$i` won't work. |
| 65 | + |
| 66 | +- `True` is `1` when casted to an integer.footnote:[https://docs.microsoft.com/en-us/powershell/scripting/lang-spec/chapter-06?view=powershell-7.2#64-conversion-to-integer[Conversion#Conversion to integer]] |
| 67 | + |
| 68 | +- Most lines of code are aimed at getting the digits needed. There is still much room for optimization. |
| 69 | + |
| 70 | +=== Composing Unicode characters |
| 71 | + |
| 72 | +[source,powershell] |
| 73 | +---- |
| 74 | +$x = ("" + $?)[$i] |
| 75 | +---- |
| 76 | + |
| 77 | +- An empty string plus a boolean turns into a string. |
| 78 | + |
| 79 | +Thanks to the `u` in `"True"`, we can compose any Unicode character now. The hex for hello world string contains `c` and `f`. Just get the two first. The `$e` variable is actually: |
| 80 | + |
| 81 | +[source,powershell] |
| 82 | +---- |
| 83 | +$e = "``u{48}e``u{6c}``u{6c}``u{6f}, ``u{57}``u{6f}``u{72}``u{6c}``u{64}!"; |
| 84 | +---- |
| 85 | + |
| 86 | +==== Escaping |
| 87 | + |
| 88 | +[source,powershell] |
| 89 | +---- |
| 90 | +iex "`$ex=""``$x{$xe}"";`$xe=""``$x{$xx}""" |
| 91 | +---- |
| 92 | + |
| 93 | +- To escape ```, `$`, `"`, just add ``` in front of them or repeat the character itself.footnote:[https://www.rlmueller.net/PowerShellEscape.htm[Escaping in PowerShell]] |
| 94 | + |
| 95 | +=== Printing the result |
| 96 | + |
| 97 | +PowerShell prints out the value of the previous expression by default, so there is no need to `iex "echo"` something. |
| 98 | + |
| 99 | +=== Other possible approaches |
| 100 | + |
| 101 | +- The output of a command can be assigned to a variable. Maybe we can find all the needed characters in some commands' default output. |
| 102 | + |
| 103 | +- `$error` stores previous error messages and requires 3 characters. |
0 commit comments