Skip to content

Instantly share code, notes, and snippets.

@taross-f
Created January 6, 2017 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taross-f/eb61c74b844fedbbe2330bef69a8c678 to your computer and use it in GitHub Desktop.
Save taross-f/eb61c74b844fedbbe2330bef69a8c678 to your computer and use it in GitHub Desktop.
<Query Kind="Program">
<Reference>&lt;RuntimeDirectory&gt;\System.dll</Reference>
<Reference>&lt;RuntimeDirectory&gt;\System.Net.dll</Reference>
<Reference>&lt;RuntimeDirectory&gt;\System.Net.Http.dll</Reference>
<Reference>&lt;RuntimeDirectory&gt;\System.Web.dll</Reference>
<NuGetReference>Microsoft.Net.Http</NuGetReference>
<NuGetReference>Newtonsoft.Json</NuGetReference>
<NuGetReference>Sendgrid</NuGetReference>
<Namespace>Newtonsoft.Json</Namespace>
<Namespace>Newtonsoft.Json.Bson</Namespace>
<Namespace>Newtonsoft.Json.Converters</Namespace>
<Namespace>Newtonsoft.Json.Linq</Namespace>
<Namespace>Newtonsoft.Json.Schema</Namespace>
<Namespace>Newtonsoft.Json.Serialization</Namespace>
<Namespace>SendGrid.SmtpApi</Namespace>
<Namespace>System.IO</Namespace>
<Namespace>System.Net</Namespace>
<Namespace>System.Web.Mail</Namespace>
</Query>
//using System;
//using System.Linq;
//using System.Collections.Generic;
class EightQueen
{
static void Main()
{
var n = int.Parse(Console.ReadLine());
var rc = Enumerable.Range(0, n)
.Select(_ => Console.ReadLine());
var board = new Board(rc);
board.InitAttackedArea();
var resultBoard = board.Explore();
resultBoard.Nodes.ForEach(row =>
Console.WriteLine(string.Join("", row.Select(x => x.QueenExists ? "Q" : ".").ToArray())));
}
}
public class Board
{
public Node[][] Nodes{ get; set; }
const int Size = 8;
public Board() {}
public Board(IEnumerable<string> rc)
{
var queens = rc.Select(x => x.Split())
.Select(x => new
{
Row = int.Parse(x[0]),
Column = int.Parse(x[1])
})
.ToArray();
Nodes = Enumerable.Range(0, Size)
.Select(row => Enumerable
.Range(0, Size)
.Select(column => new Node
{
QueenExists = queens.Any(x => x.Row == row && x.Column == column)
})
.ToArray())
.ToArray();
}
// 初期配置のアタックエリア設定
public void InitAttackedArea()
{
Nodes.ForEach((x, row) => x.ForEach((node, column) =>
{
ApplyAttackedArea(row, column);
}));
}
public void ApplyAttackedArea(int row, int column)
{
var node = Nodes[row][column];
if (!node.QueenExists)
return;
// row
Nodes[row].ForEach(x =>
{
x.IsAttackedArea = true;
});
// column
Nodes.ForEach(rows =>
{
rows[column].IsAttackedArea = true;
});
// from left top to right bottom
for (int r = row - Size, c = column - Size; r < Size && c < Size; r++, c++)
{
// 一旦はみ出させてループを開始しているので、はみ出している場合はチェックしない
if (r >= Size || c >= Size || r < 0 || c < 0)
continue;
Nodes[r][c].IsAttackedArea = true;
}
// from right top to left bottom
for (int r = row - Size, c = column + Size; r < Size && c >= 0; r++, c--)
{
// 一旦はみ出させてループを開始しているので、はみ出している場合はチェックしない
if (r >= Size || c >= Size || r < 0 || c < 0)
continue;
Nodes[r][c].IsAttackedArea = true;
}
}
public Board Clone()
{
return new Board
{
Nodes = Nodes.Select(x =>
x.Select(y => new Node
{
IsAttackedArea = y.IsAttackedArea,
QueenExists = y.QueenExists
})
.ToArray())
.ToArray()
};
}
public Board Explore()
{
return Enumerable.Range(0, Size)
.Where(row => Nodes[row].All(x => !x.QueenExists))
.Select(row => Enumerable.Range(0, Size)
.Select(column => Explore(this, row, column))
.FirstOrDefault(x => x != null))
.DefaultIfEmpty(this)
.FirstOrDefault();
}
private static Board Explore(Board board, int r, int c)
{
if (board.Nodes[r][c].IsAttackedArea)
return null;
// checkしたよ判定
board.Nodes[r][c].IsAttackedArea = true;
// 先がダメだったとき用に先にはクローンしたものを渡す
var b = board.Clone();
b.Nodes[r][c].QueenExists = true;
// 今回設定したqueenのアタックエリア設定
b.ApplyAttackedArea(r, c);
var nextRow = Enumerable.Range(r + 1, Size - (r + 1))
.Where(x => b.Nodes[x].All(node => !node.QueenExists))
.DefaultIfEmpty(Size)
.Min();
// 次がなかったら探索終了。ここのboardが上まで帰ってく
if (nextRow >= Size)
return b;
return Enumerable.Range(0, Size)
.Where(x => !b.Nodes[nextRow][x].IsAttackedArea)
.Select(x => Explore(b, nextRow, x))
.FirstOrDefault(x => x != null);
}
}
public class Node
{
public bool QueenExists { get; set; }
public bool IsAttackedArea { get; set; }
}
// これないとめんどくさすぎるので。
public static class MyExtensions
{
public static void ForEach<T>(this IEnumerable<T> e, Action<T> action)
{
foreach (var element in e) action(element);
}
public static void ForEach<T>(this IEnumerable<T> e, Action<T, int> action)
{
var i = 0;
foreach (var element in e) action(element, i++);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment