Skip to content

Commit 1d52c9f

Browse files
authored
Add PowerShell solution (#36)
* Add PowerShell solution * Update ranking * Fix cross reference
1 parent 8c92f93 commit 1d52c9f

File tree

4 files changed

+206
-2
lines changed

4 files changed

+206
-2
lines changed

OverflowCat/README.adoc

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
= PowerShell
2+
3+
xref:README_en.adoc[English] | 简体中文
4+
5+
image:http://telegra.ph/file/cb631e2869a7540a84b87.png[screenshot]
6+
7+
== 代码
8+
9+
选择的 3 个字母:`i`、`e`、`x`。
10+
11+
[source,powershell]
12+
----
13+
$i=$?+$?
14+
$e=$i+$i
15+
$xi=$x=$e+$i
16+
$xe=""+$x+$x
17+
$xx=""+$x+--$e
18+
$x=(""+$?)[$i]
19+
iex "`$ex=""``$x{$xe}"";`$xe=""``$x{$xx}"""
20+
$ii=$e+++$i
21+
$ix=$ii+$i
22+
$ei=$e*$i
23+
$x="``$x{"
24+
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}!"""
25+
$e
26+
----
27+
28+
压成一行时语句结尾需要有分号。
29+
30+
[source,powershell]
31+
----
32+
$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
33+
----
34+
35+
=== 环境
36+
37+
*PowerShell 7.2.5*
38+
39+
需要自行安装,Windows 自带的版本较旧,没有 Unicode 转义字符。
40+
41+
代码可以在终端直接粘贴,或者通过 `.\x.ps1` 运行。
42+
43+
== 原理
44+
45+
=== 选择字母
46+
47+
PowerShell 中无法对 Char 进行加减操作,显式地进行类型转换也需要类似 `[char]65` 至少 4 个字母。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]]所以只能考虑 eval。PowerShell 中的命令名都很长,不过 Invoke-Expression 有别名 `iex`。另外有一个可以执行字符串的操作符 `&`,但是只能是命令名,不能带参数。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]]
48+
49+
=== 第一个数字
50+
51+
因为不能直接出现数字了,所以需要想办法得到第一个 Int 类型的值。发现数组下标为空字符串 `''` 时可以得到数组的第一个元素,但是如果想要后面的字母的话,PowerShell 并没有提供 pop 等函数。footnote:[https://stackoverflow.com/questions/24754822/powershell-remove-item-0-from-an-array[PowerShell Remove item 0 from an array - Stack Overflow]]数字字面量也都至少需要有 `0` 出现。所以只能通过其他类型隐式转换出 Int 来。
52+
53+
[source,powershell]
54+
----
55+
$i = $? + $?
56+
----
57+
58+
- `$?` 表示上一条命令的返回值,在初始时和上一条命令没有出错时为 `True`。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]]
59+
60+
- PowerShell 中的 `==` 是 `-eq`,需要额外的字母。
61+
62+
- 当 Bool 类型转换为整数时,`True` 是 `1`,故 `$i` 为 `2`。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]]
63+
64+
剩下的大部分操作都是在构造其他数字,代码的长度应该可以再压缩一点。
65+
66+
=== 构造 Unicode
67+
68+
[source,powershell]
69+
----
70+
$x = ("" + $?)[$i]
71+
----
72+
73+
- `+` 运算符的两个参数类型不一致的时候,会将第二个参数隐式转换为第一个参数的类型。故此处 `$e` 为 String `"True"`。
74+
75+
至此,我们有了所需的数字和字母 `u`,可以用 `"`u{x}"` 来生成一切字符了。不过,`"Hello World!"` 除了可以直接输入的 `e`、空格和 `!`,十六进制值中还需要 `c` 和 `f`。幸好这两个的编码分别为 `63` 和 `66`,没有 a-f 出现。`$e` 实际上就是:
76+
77+
[source,powershell]
78+
----
79+
$e = "``u{48}e``u{6c}``u{6c}``u{6f}, ``u{57}``u{6f}``u{72}``u{6c}``u{64}!";
80+
----
81+
82+
==== 转义字符
83+
84+
[source,powershell]
85+
----
86+
iex "`$ex=""``$x{$xe}"";`$xe=""``$x{$xx}"""
87+
----
88+
89+
- 字符串用双引号的好处是可以直接嵌入变量。如果要 escape 的话,需要在 `$`、`"`、``` 前面加上 ```;`"` 也可以自身重复两次 `""` 来 escape。footnote:[https://www.rlmueller.net/PowerShellEscape.htm[Escaping in PowerShell]]
90+
91+
=== 打印值
92+
93+
PowerShell 默认打印出前一个表达式的值,所以不需要拼凑出 `"echo"` 再 `iex` 什么的。
94+
95+
=== 其他可能的方法
96+
97+
- 变量赋值时可以直接是命令的输出。比如旧版 PowerShell 可以通过 `$ls = ls; $ls[x][x]` 拿到 ls 命令表头具体的一个 Char,或许有的命令的输出包含全部所需的字母。但是新版中大部分命令的输出不再是字符串而是对象了,两次下标拿到的仍然和原结果一样。
98+
99+
- `$error` 是一个存放了错误信息字符串的数组。footnote:[https://www.tutorialspoint.com/what-is-use-of-error-variable-in-powershell[What is use of $error variable in PowerShell?]]不过,错误会直接输出,不符合「该程序运行后输出 Hello, World!, 有且仅有该内容,要求分毫不差」的要求。

OverflowCat/README_en.adoc

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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.

OverflowCat/x.ps1

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$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

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@
3333
| 9 | [Jack-Works](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/Jack-Works) | 126 bytes | JavaScript | |
3434
| 10 | [benpigchu](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/benpigchu) | 140 Bytes | Python | 大概还能再压,但是懒 |
3535
| 11 | [dantmnf](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/dantmnf) | 247 Bytes | Ruby | 本来是一个字母数字都不带,随便改改( |
36-
| 12 | [vantis](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/vantis) | 792 Bytes | Java | 能不能写出来纯看字母选得好不好 =。= |
37-
| 13 | [GalvinGao](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/GalvinGao) | 3.3 KB | JavaScript | 感谢鼹鼠( |
36+
| 12 | [OverflowCat](/OverflowCat) | 261 Bytes | PowerShell | 为什么不试试 M$ 的功率壳呢? |
37+
| 13 | [vantis](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/vantis) | 792 Bytes | Java | 能不能写出来纯看字母选得好不好 =。= |
38+
| 14 | [GalvinGao](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/GalvinGao) | 3.3 KB | JavaScript | 感谢鼹鼠( |
3839
| - | [许兴逸](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/%E8%AE%B8%E5%85%B4%E9%80%B8) | 124Bytes | Haskell | 我import了Data.Char【
3940
| - | [谓道之求](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/%E8%B0%93%E9%81%93%E4%B9%8B%E6%B1%82) | 138 Bytes | Matlab | 过几天就符合规则了) |
4041
| - | [Nyaacinth](https://github.com/InvoluteHell/ThreeKeysProgramming/tree/master/Nyaacinth) | 248 Bytes | Lua (LuaJIT) | 做不到,但是 Lua 值得有姓名! |

0 commit comments

Comments
 (0)