POH6+ 「え、妻が松江?」松江Ruby会議07協賛 回文作成プログラミングコンテストをC#で解いてみた


POH6+

「え、妻が松江?」松江Ruby会議07協賛 回文作成プログラミングコンテスト|POH6+

処理の流れ

  1. 入力値から単語リスト生成
  2. 回文の左半分生成
  3. 回分の真中生成
  4. 左半分+真中+左半分の反転を出力

左半分の生成

  1. 単語リストから重複削除
  2. 単語が逆転した単語と一致するか辞書順で小さい かつ 反転した単語が単語リストに存在するで抽出
  3. 辞書順でソート
  4. 単語を反転して反転前と一致する場合、単語リストに登場する回数の1/2回分、左半分文字列に追記
  5. 単語を反転して反転前と一致しない場合、単語リストに登場する回数と反転した単語が単語リストに登場する回数が少ない方の回数分、左半分文字列に追記

真中の生成

  1. 単語リストから重複削除
  2. 単語を反転して反転前と一致する かつ 単語リストに登場する回数が奇数回で抽出
  3. 辞書順でソートした内の最初の要素、要素がない場合は空文字

コード

Program.cs
using System;
using System.Linq;

namespace Kaibun
{
    class Kaibun
    {
        static void Main(string[] args)
        {
            var list = Enumerable.Repeat(0, int.Parse(Console.ReadLine())).Select(x => Console.ReadLine()).ToArray();

            // 文字列逆転用Func
            Func<string, string> reverse = x => string.Join("", x.Reverse());

            // 左半分
            var half = list.Distinct()
                .Where(x => string.Compare(x, reverse(x)) <= 0 && list.Contains(reverse(x)))
                .OrderBy(x => x).Aggregate("", (a, s) => a += string.Join("",
                    Enumerable.Repeat(s, s == reverse(s)
                        ? list.Count(x => x == s) / 2 // 左右対称な単語
                        : Math.Min(list.Count(x => x == s), list.Count(x => x == reverse(s)))))); // 左右対称でない

            // 真中
            var center = list.Distinct()
                .Where(x => x == reverse(x) && list.Count(y => x == y) % 2 == 1)
                .OrderBy(x => x).FirstOrDefault() ?? "";

            Console.WriteLine(half + center + reverse(half));
        }
    }
}