Codingame『Sandpile addition』

砂場用 さくさくあそび砂 20kg(13.3L)【放射線量報告書付き】
www.codingame.com


カタストロフィー現象って言うんだっけ?

 高さが4以上なら-4して上下左右に+1すればいいんだから、特に難しくない。
n×n配列内に高さ4以上がある事をどうやって知るのかが工夫のしどころかな?


 誰でも思いつくような工夫だけど、
地ならしと高さチェックで配列を2ループさせる所を、1ループでできるようにした。


コード
using System;
using System.Linq;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;

/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 **/
class Solution
{
    static void Main(string[] args)
    {
        SandBox sb = new SandBox();
        sb.LandLeveler();
        sb.Draw();
    }
}

public class SandBox
{
    //砂場のサイズ
    private int size;
    //砂場の状態
    private int[,] sandState;

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public SandBox()
    {
        this.InitSandBox();
    }

    /// <summary>
    /// 地ならし
    /// </summary>
    public void LandLeveler()
    {
        while (true)
        {
            bool over3 = false;

            for (int y = 0; y < this.size; y++)
            {
                for (int x = 0; x < this.size; x++)
                {
                    if (this.sandState[x, y] > 3)
                    {
                        this.sandState[x, y] -= 4;
                        over3 = over3 | this.DistributeSand(x - 1, y);
                        over3 = over3 | this.DistributeSand(x + 1, y);
                        over3 = over3 | this.DistributeSand(x, y - 1);
                        over3 = over3 | this.DistributeSand(x, y + 1);
                    }
                }
            }

            if (over3 == false)
            {
                break;
            }
        }
    }

    /// <summary>
    /// 砂の振り分け
    /// </summary>
    private bool DistributeSand(int x, int y)
    {
        if (x < this.size & x >= 0 & y < this.size & y >= 0)
        {
            if ((++this.sandState[x, y]) > 3)
            {
                return true;
            }
        }

        return false;
    }

    /// <summary>
    /// 砂場の初期化
    /// </summary>
    private void InitSandBox()
    {
        this.PrepareSandBox();
        this.ReadSandBox();
    }

    /// <summary>
    /// 砂場の準備
    /// </summary>
    private void PrepareSandBox()
    {
        this.size = int.Parse(Console.ReadLine());
        this.sandState = new int[this.size, this.size];
    }

    /// <summary>
    /// 砂場の読み込み
    /// </summary>
    private void ReadSandBox()
    {
        for (int p = 0; p < 2; p++)
        {
            for (int y = 0; y < this.size; y++)
            {
                string row = Console.ReadLine();

                for (int x = 0; x < this.size; x++)
                {
                    this.sandState[x, y] += (int)(row[x] - '0');
                }
            }
        }
    }

    /// <summary>
    /// 砂場の描画
    /// </summary>
    public void Draw()
    {
        for (int y = 0; y < this.size; y++)
        {
            for (int x = 0; x < this.size; x++)
            {
                Console.Write(this.sandState[x, y]);
            }
            Console.WriteLine("");
        }
    }
}

『夜桜四重奏~ヨザクラカルテット~(20)』を読み終わった

夜桜四重奏~ヨザクラカルテット~(20) (シリウスKC)
 猫の概念が壊れる。


三行感想

・映像にモザイクかけるお仕事が忙しくなるな!
・戦力として見ると魅力的なので、桜新町に軍や外人部隊からオファー来る?
・ちょっと妖怪になるだけで仕事の効率が上がるなら、経営者が欲しがりそうだ



『はにょう5+』プレイ(4)

茄子(1) (アフタヌーンコミックス)



漆黒のガーゴイル

 正直もうあかん、また全滅や…と思ってたら勝てた。
なぜ勝てたのか未だによくわからん。


なすーん&ドラ子

 なすーんのフィールド・アクションリミテイションが一番驚いた。
攻撃したくても選択アイコンが消えてるなんて酷い。
戦闘自体はさっさとドラ子を排除したので簡単だった。



Codingame『Highest truncated pyramid』

(トミショウ) 富商 パワーストン 水晶 クリスタル ピラミッド 神秘 ピラミット 天然石 開運 風水 CK20
 よくあるCの練習問題っぽいけど、台形になったとたんにややこしくなった感!


問題

 N個のレンガ(*)を全部使ってピラミッドを作る。
例えばN = 1なら、こう。

N=6ならこう。

**
***
N=7の場合なら、
***
****
こんな感じ、と。


どうしようか

 一発で解決する方法を思いつかなかったので、高さから攻める事にした。
台形の上底をa、高さをh、与えられるブロック数をNとする。
等差数列の和の公式を使うと、こう。
{ N = \frac{h(2a+h-1)}{2} }
高さhから上底aを求めたいのでわちゃわちゃと変形するとこうなる。
{a = \frac{2N-h^{2} +h}{2h}}
hの値を変えて突っ込むとaの値が求まるので、最も大きいhの値を調べればいい。
ただし、aは自然数の範囲。


ちょっと面白い部分

 これ、出力を見てみるとh=2の時のNが全部素数になってる。



コード
using System;
using System.Linq;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;

/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 **/
class Solution
{
    static void Main(string[] args)
    {
        int total = int.Parse(Console.ReadLine());
        Console.Error.WriteLine(total);

        TP2 pyramid = new TP2(total);

        Console.WriteLine(pyramid.Draw());
    }


    //クラス内クラス
    public class TP2
    {
        private int total;
        private int width;
        private int height;

        //コンストラクタ
        public TP2(int N)
        {
            total = N;
            height = 1;
            width = N;

            ps();
        }

        //台形の上底と高さを調べる
        private void ps()
        {
            int bt = total * 2;
            int ht = (total + 1) / 2;

            for (int h = 2; h <= ht; h++)
            {
                //高さhから上底aを計算する
                int a = (bt - h * h + h) / (2 * h);
                //上底aと高さhからサイズsを求める
                int s = (h * (2 * a + h - 1)) / 2;

                if (a > 0 & s == total)
                {
                    width = a;
                    height = h;
                }
            }
        }

        //台形を描画した文字列を返す
        public string Draw()
        {
            string str = "";

            for (int h = 0; h < height; h++)
            {
                string tmp = "";

                for (int w = 0; w < width + h; w++)
                {
                    tmp += "*";
                }

                str += tmp;

                if (h < height - 1) str += System.Environment.NewLine;
            }

            return str;
        }
    }

}
追記

 もしかしたら、こうしたらより早くなるのかもしれない。

        private void ps()
        {
            int bt = total * 2;
            int ht = (total+1) / 2; 

            for(int h = IntRootOf2N(); h >= 2; h--)
            {
                int a = (bt - h * h + h) / (2 * h);
                int s = (h * (2 * a + h - 1)) / 2;

                if (s == total)
                {
                    width = a;
                    height = h;
                    break;
                }
            }
        }

        private int IntRootOf2N()
        {
            return (int)(Math.Sqrt(2 * total));
        }