using System.Globalization;
using System.Collections.Generic;
using System.Diagnostics;
public static void Main()
`~ 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+
qQ wW eE rR tT yY uU iI oO pP [{ ]} \|
aA sS dD fF gG hH jJ kK lL ;: '""
zZ xX cC vV bB nN mM ,< .> /?
var positionTable = BuildPositionTable(qwerty, true, 3);
var adjacentPoints = positionTable.Select(kvp => (K: kvp.Value, V: GetSlantedAdjacent(kvp.Key)));
var a = positionTable.SelectMany(kvp => GetSlantedAdjacent(kvp.Key), (kvp, pos) => (K: kvp.Value, V: pos))
.Join(positionTable, adj => adj.V, pos => pos.Key, (adj, posCol) => (Key: adj.K, posCol.Value))
.Where(kvp => kvp.Value.Any())
.SelectMany(kvp => kvp.Key, (kvp, c) => (c, Val: kvp.Select(a => a.Value)))
.ToDictionary(kvp => kvp.c, kvp => kvp.Val);
Console.WriteLine($"Key: {item.Key}");
foreach (var v1 in item.Value)
Console.WriteLine($" Value: { v1 }");
foreach (var v2 in v1.ToList()) {
private static Dictionary<Point, string> BuildPositionTable(string layout, bool slanted, int xUnit) =>
ParseLayout(layout).SelectMany((line, y) =>
return line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
.Select(token => (Key: new Point(x: (line.IndexOf(token) - (slanted ? y : 0)) / xUnit, y), token));
}).ToDictionary(kvp => kvp.Key, kvp => kvp.token);
private static IEnumerable<string> ParseLayout(string layout)
using StringReader reader = new StringReader(layout);
while ((readText = reader.ReadLine()) != null)
if (string.IsNullOrWhiteSpace(readText)) continue;
private static Point[] GetSlantedAdjacent(Point point)
private static Point[] GetAlignedAdjacent(Point point)
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y) => (X, Y) = (x, y);
public override string ToString() => $@"{{X: {X}, Y: {Y}}}";
public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
public static implicit operator (int x, int y)(Point value) => (value.X, value.Y);
public static implicit operator Point((int x, int y) value) => new Point(value.x, value.y);