1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【電脳少女プログラミング2088】 F#で解いた |> Geminiを混乱させた

Posted at

paizaのプログラミングゲーム【電脳少女プログラミング2088 ─壊レタ君を再構築─】を F# で解いてみました。
ランクAだけ終わりませんでした。
ちょっと悔しいです。

D ランク

郊外のスラム街

stdin.ReadLine()
|> int
|> (fun price -> price / 2 + 100)
|> printfn "%d"

ネオン街の裏路地

let readInt () = stdin.ReadLine() |> int
let n = readInt ()
Seq.init n (fun _ -> readInt ()) |> Seq.max |> printfn "%d"

カジノ

Seq.init 3 (fun _ -> stdin.ReadLine() |> int)
|> Seq.zip [ 1; 5; 10 ]
|> Seq.sumBy (fun (num, price) -> num * price)
|> printfn "%d"

Cランク

自然の残る公園

type Coordinate = { posX: int; posY: int }

let splitReadInt () =
    stdin.ReadLine().Split(' ') |> Array.map int

let distance pos1 pos2 =
    let dx = pos1.posX - pos2.posX
    let dy = pos1.posY - pos2.posY
    dx * dx + dy * dy

let n, initPos =
    let [| n; x; y |] = splitReadInt ()
    n, { posX = x; posY = y }

Seq.init n (fun _ -> splitReadInt ())
|> Seq.map (fun arr -> { posX = arr.[0]; posY = arr.[1] })
|> Seq.map (distance initPos)
|> Seq.indexed
|> Seq.minBy snd
|> fst
|> ((+) 1)
|> printfn "%d"

一気にコードが長くなりました。他の解かれた皆さんはどうだったでしょうか。

廃マンションの一室

実は下のコードを提出する前に、パズルを解くようにコードをこねくり回して、長~いコードを提出しました。
そちらも正解にはなったのですが、特殊とはいえ3進法なのに3進法をあまり活用していないような気がして、3進法を調べ直しました。
そうしたところ平衡三進法(天秤三進法とも)を偶然見つけ、これを一度学び直してから、最初からプログラミングし直しました。
その結果がこちらです。

open System
let readFloat () = stdin.ReadLine() |> float

let toTernary input =
    let rec toTernary' input' str =
        let quotient = Math.Floor(input' / 3.0)

        let alterNumber =
            match Math.IEEERemainder(input', 3.0) with
            | 0.0 -> "2"
            | 1.0 -> "0"
            | _ -> "1"

        let newStr = alterNumber + str

        match quotient with
        | 0.0 -> newStr
        | _ -> toTernary' (quotient + 1.0) newStr

    toTernary' (input + 1.0) ""

toTernary (readFloat ()) |> printfn "%s"

このコードF#の通常の除算と剰余算を使うと、入力値がマイナスだったときに答えが合いません。
通常の除算の代わりに System.Math.Floor と / , 普通の剰余算 % の代わりに System.Math.IEEERemainder を使う必要があります。
float 使わなくても良さそうなのに float に変換しているのは、この2つの関数を使うためです。
使わない場合はコード中央付近の | 0.0 -> "2" から始まるマッチパターンを調整する必要があります。
Pythonでは通常の除算、剰余算のままで大丈夫なようです。
その他の言語は分かりません。

で、自分は平衡三進法を学んだあとコードをこねくり回してこのコードにたどり着いたのですが、このコードだと問題なく動くものの、なぜ平衡三進法を求める部分に毎回1を加えて渡す( input + 1.0 と quotient + 1.0 の部分)とうまく動くのか分かりませんでした。

コードを直すに疲れてしまった自分はこの質問を Gemini に投げてしまったのですが、その結果 Gemini を混乱させてしまいました。
その混乱っぷりが面白かったのですが、それは本件の趣旨からはちょっと外れるので、最後に載せます。

Bランク

ギャングのアジト

let n = stdin.ReadLine() |> int
let art = Array.init n (fun _ ->
    stdin.ReadLine().Split()
    |> Array.map int)

let isSinmetric =
    [ 0 .. n - 1 ]
    |> List.forall (fun i ->
    [ 0 .. n - 1 ]
    |> List.forall (fun j ->
    art.[j].[i] = art.[j].[n - 1 - i]))

printfn "%s" (if isSinmetric then "Yes" else "No")

一番通りの繁華街

let n = stdin.ReadLine() |> int

let areaMap =
    Array.init n (fun _ -> stdin.ReadLine() |> Seq.map (fun c -> c = '.') |> Seq.toArray)

let countSquares =
    seq {
        for x in 0 .. n - 2 do
            for y in 0 .. n - 2 do
                if areaMap.[x].[y] then
                    let maxDelta = min (n - x - 1) (n - y - 1)

                    for delta in 1..maxDelta do
                        if
                            areaMap.[x + delta].[y]
                            && areaMap.[x].[y + delta]
                            && areaMap.[x + delta].[y + delta]
                        then
                            yield 1
    }
    |> Seq.sum

printfn "%d" countSquares

Sランク

思い出の屋上

とここまで解いたところで時間切れ、23,24日は時間がとれないから今日中にQiitaに投稿までしないと間に合わないと思いました。
ただSランクの問題なんて見たこともないから、ちょっと見てみようと思い覗いてみました。
案の定コードの目安が立たない。
こうやって経路探索すればいいのかなと思うけど、それじゃあこんな配置だったらどうするの?自問自答の結果振り出しに。
諦めかけたときフッと、「縄張りがどこにどれだけ広がっているかなんて考えずに、全部の点から全部の縄張りまdの距離を求めちゃえばいいんじゃないの」と考えつき、大急ぎでコーディングしました。
その結果がこちら

let readArrayInt () =
    stdin.ReadLine().Split() |> Array.map int

let height, width, gangNumber =
    let input = readArrayInt ()
    input.[0], input.[1], input.[2]

let territories =
    Array.init gangNumber (fun _ ->
        let input = readArrayInt ()
        (input.[0], input.[1], input.[2]))

let calcDistance (x1, y1) (x2, y2, d) = abs (x1 - x2) + abs (y1 - y2) - d - 1

let calcMaxDistance =
    seq {
        for x in 1..height do
            for y in 1..width do
                let distance =
                    territories
                    |> Array.map (fun (x1, y1, d) -> calcDistance (x, y) (x1, y1, d))
                    |> Array.min

                yield distance
    }
    |> Seq.max

printfn "%d" calcMaxDistance

ある1点(x,y)からどれかのギャングの縄張りの中央(x1, y1)マンハッタン距離は問題文に書かれている通り|x1-x|+|y1-y|、これよりその地点から作成できる縄張りは、両者の距離からギャングの縄張りの広さdと1を減算すれば求まります。

全てのギャングの縄張りとの間に作成できる縄張りの最小の距離を求め(最小の距離以外のギャングまでは、その最小の距離のギャングの位置が邪魔して縄張りを広げられない)、さらにその全ての最小の距離の中の最大値を求めれば、答えに辿りつけます。

paiza の F# の実行環境は F# Interactive なのでコンパイルされてませんが、全部計算させても Test case 4 が 0.10 秒なだけで、その他は 0.03 秒でした。

正解.jpg

(余談) Geminiが混乱した!

廃マンションの一室のところで書いたとおり、なぜ平衡三進法を求める部分に毎回1を加えて渡すとうまく動くのか分からず Gemini に「どうしてうまくいくの?」と質問してしまいました。
Gemini は Web版の Gemini Flash Thinking Experomental です。
ただし今回の 2,1,0 を使う特殊な平衡三進法ではなく、-0+ を使うより一般的な平衡三進法にして質問しました。
最初に少し「いい質問です」などと講釈を述べたあと、説明に入りました。

三進法0.png

すべり出しは順調です。

三進法2.png
コンピューターが「あれ?」って返すのあり?

三進法3.png
「... まだ違う ...」「... 計算が合わない...」って普通推論部分で済ますことじゃないの?

三進法4.png
'-+-'でないと、同じことを繰り返してます。

三進法5.png
期待してるよ。

三進法6.png
敵に襲われて四次元ポケットの中身をばら撒くドラ◯もん並の混乱っぷりです。

三進法7.png
「ああ、情けない」とか「ハッ!」とかAIからの答えで見るとは思いませんでした。
DeepSeek R1 が出てきたとき、推論部分に Wait!(待て) と書かれていて、AIなのに人間臭いと書かれてた X の投稿を見た覚えがありますが、Gemini は人間を通り越して猿並みです。
このあとも間違えを繰り返しますが、途中であれだけ固執していた -5 の平衡三進法(ここではバランス三進法)表記を求めるのを諦めて

三進法8.png
魔法かい!魔法って言葉、コンピューターが使っていいの?異世界転生したら n + 1 が魔法だったってやつ?
まあ「魔法」が日本語に訳される前は Magic かなにかで、数値のマジックのような意味してたんじゃないのかなと予想しますが。
で最後は

三進法9.png
無理だよ~。自信満々によくそんなことが言えるな!
こんなAIの回答は初めて見ました。
AIの問題はハルシネーションだけではなく、分からない問題を分からないと答えられないことかもと思いました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?