배수구 아래로


12

여러 번 수평 파이프로 연결된 4 개 이상의 수직 파이프가 있고 수직 파이프에 공이나 물을 떨어 뜨려야하는이 미니 게임이 발생했습니다.
내가 아는 두 종류가 있습니다 :

  • 출구 중 하나에서 양동이 / 바구니에 물건을 넣습니다 (어떤 파이프를 던질 지 추측합니다)
  • 물체가 어떤 파이프에서 나오는지 맞춰보세요.

샘플 파이프 :

|       |       |-------|  
|-------|       |-------|  
|       |-------|       |  
|-------|-------|-------|  
|       |-------|       |  
|-------|       |-------|  
|-------|       |-------|  
|       |-------|       |  

기본 규칙 :

  • 수평 파이프를 통과 할 때 가능하면 물체가 내려갑니다
  • 수직 파이프를 통과 할 때 물체는 가능하면 수평 파이프로 바뀝니다.

작업

  • 임의의 파이프 그리드를 생성하는 프로그램을 작성하십시오 (샘플 파이프 참조).
  • 최소 4 개의 수직 파이프와 최소 10 개의 수평 파이프가 있어야합니다.
  • 수직 파이프의 길이는 당신에게 달려 있습니다.
  • 물체가 바닥에 닿는 경로를 보여주고 얼마나 많은 회전을했는지 보여줍니다.
  • (선택 사항) 시작점 결정을위한 입력, 파이프 번호는 1.N입니다. 왼쪽에서 오른쪽으로.

디스플레이:

 | vertical pipe
 - horizontal pipe
 : vertical pipe used by the object
 = horizontal pipe used by the object
 V Object starting point
 ^ Object ending point

예:

V
:       |       |-------|
:=======:       |-------|
|       :=======:       |
|-----!-:=======:       |
|       :=======:-------|
|-------|       :=======:
|-------|       :=======:
|       :=======:       |
        ^
14 turns were taken to get to the end.

상세
객체가 파이프 1에 들어가고 아래로 이동하기 시작하고 첫 번째 수평 파이프로 왼쪽으로 이동합니다.
다시 두 번째 파이프로 내려간 다음 세 번째 파이프로 U 턴합니다.
세 번째 파이프 끝에서 느낌표가 표시
됩니다. 결과에 포함되어서는 안되지만, 객체가 똑바로 나아 갔을 수 있음을 나타 내기 위해 이것을 사용했습니다.
그러나 규칙 번호 1은이를 방지합니다.

우승자는 지금 24-02-2014 (dd-mm)부터 3 주 동안 투표로 결정됩니다.

행복한 코딩 ^. ^


7
물체가 떨어지고 파이프가 왼쪽에 있고 같은 높이에 파이프가 오른쪽에 있으면 어떻게됩니까?
Howard

2
또한 입력 및 출력이 고정되어 있기 때문에 인기 콘테스트 를 만드는 것이 좋지 않다고 생각합니다 .
Howard

@Howard-그렇다면 무엇으로 태그 하시겠습니까? "우승자는 투표에 의해 결정될 것입니다."저에게 인기있는 상황 인 것 같습니다. 여기에는 골프 나 다른 성공 기준이 없으며 고정 된 문자열 출력이 아닙니다
jimbobmcgee

1
@DavidCarraher-물이 아닌 핀볼은 어떻습니까? 각 수평 파이프가 약간 자성을 띠고 있습니까? 그리고 공이 다운 파이프 단면의 끝에 도달하면 수평으로 들어가면 꺼집니다. 레이저 스트립 와이어로. :-) (자석, 어떻게 작동합니까?!) (레이저 인계 철선 (지뢰에 연결된 선)에 어떻게 그들이 작동!?)
jimbobmcgee

1
@ Fabinout-피의 숙제가 아닌 것이 좋습니다! 나는 주중에 이것에 대한 나의 대답을 제압하는 데 아주 좋은 일을 너무 많이 낭비했습니다!
jimbobmcgee 2013

답변:


24

매스 매 티카

2D 코드는 물의 경로를 보여주는 그래프를 생성합니다. 3D 디스플레이로 편리한 교차 점검을 위해 정점 번호를 표시했습니다. 일반적으로 정점 번호는 숨겨집니다.

입력:

r=10;c=7;
result=flow2D[{r,c},3]

실제로 결과에는 여러 개체가 포함됩니다. 첫 번째 객체 result[[1]]는 여기에 표시된 2D 그래프입니다.

2D


3 차원 파이프는 Tube3 개의 공간에 3 차원 선으로 그려져 있습니다. 임의로 생성 된 3 차 좌표를 따라 2D 그래프의 정점을 기준으로 계산 된 좌표 (이를 통해 코드가 실행될 때마다 파이프가 y를 따라 다른 위치를 가정 할 수 있습니다.)

축은 독자가 3D 렌더링이 실제로 2D 렌더링을 기반으로하고 있음을 확신 할 수 있도록 표시됩니다.

여기서 관심있는 3D 입력은 다음과 같습니다.

Graphics3D[{CapForm[None],verticalPipes,allRungs,Darker@Red,connections},
ImageSize->600,Axes-> True,Ticks->{Range[1,2 r,2],Range[c],Range[10]},ViewPoint->{0,-2,1.5}]

숫자 또는 행, 열 및 입력 열은 2D 코드에서 가져옵니다. 다시 입력 할 필요는 없습니다.

3D

2D 코드

앞으로는 2D 및 3D 용 코드를 문서화하고 정리할 것입니다.

flow2D[{rows_,columns_},startColumn_]:=
Module[{r=rows,c=columns,g,j,h,ends,middle,midcuts,direction="down",turns=0,path,rungs},

   (*complete gridgraph*)
g=GridGraph[{r,c},VertexSize-> Medium,GraphStyle->"Prototype",EdgeStyle->"Thick",
  VertexLabels->"Name",ImagePadding-> 30,ImageSize->470];

(*horizontal pipes that must be removed*)
ends=Table[r(c1-1)+r1\[UndirectedEdge] r(c1)+r1,{c1,1,c-1},{r1,{1,r}}];

(*horizontal pipes to consider removing *)
middle=Table[r(c1-1)+r1\[UndirectedEdge] r(c1)+r1,{c1,1,c-1},{r1,2,r-1}];
midcuts=RandomSample[#,RandomInteger[Round[{r/15,2r/5}]]]&/@middle;

rungs=Flatten[midcuts(*Join[ends,midcuts]*)];

j=EdgeDelete[g,Flatten[Join[ends,midcuts]]];

h[path_]:= Module[{start=path[[-1]],right,left,up,down,newnodes}, 
     {v=NeighborhoodGraph[j,start,1,(*VertexLabels\[Rule]"Name",*)ImagePadding->25],
     VertexList[v]};newnodes=Complement[VertexList[v],path];
     If[newnodes=={},path,  
     h[Append[path,
  Switch[direction,
   "down",Which[
     MemberQ[newnodes,start+r],(turns++;direction="right";start+r),
     MemberQ[newnodes,start-r],(turns++;direction="left";start-r),
     MemberQ[newnodes,start-1],start-1],
   "right",Which[
     MemberQ[newnodes,start-1],(turns++;direction="down";start-1),
     MemberQ[newnodes,start+r],start+r],  
   "left",Which[
     MemberQ[newnodes,start-1],(turns++;direction="down";start-1),
     MemberQ[newnodes,start-r],start-r]
    ]]]]];
{HighlightGraph[j,path=h[{r*startColumn}],ImageSize->300],path,rungs,ends,midcuts}]

convert[node_,r_,c_]:=Append[footing[[Quotient[node-1,r]+1]],Mod[node-1,r]+1(*Mod[node,r]*)]
connect[a_\[UndirectedEdge]b_,r_,c_]:=Tube[Line[{convert[a,r,c],convert[b,r,c]}],0.2]

3D 코드 및 결과

r=10;c=7;
result=flow2D[{r,c},3];
g2D=result[[1]];
path2D=result[[2]];
\[AliasDelimiter]
xScale=2;
footing = {#, RandomInteger[{1, 6}]} & /@ Range[1,xScale c, xScale];
verticalPipes=Tube[Line[{Append[#,1],Append[#,r]}],.19]&/@footing;
Graphics3D[{CapForm[None],verticalPipes},ImageSize->600,Axes->True,AxesEdge->Automatic,ViewPoint->{0,-2,1.5},
Ticks->{Range[1,2 r,2],Range[c],Range[10]}];

path3D=UndirectedEdge@@@Partition[Riffle[stops=path2D,Rest@stops],2];
allRungs=connect[#,r,c]&/@rungs;
connections=connect[#,r,c]&/@path3D;

path2D;
g2D
Graphics3D[{CapForm[None],verticalPipes,allRungs,Darker@Red,connections},
ImageSize->600,Axes-> True,Ticks->{Range[1,2 r,2],Range[c],Range[10]},ViewPoint->{0,-2,1.5}]

2
당신이 통로를 렌더링 할 수 있다면, 이것은 확실히 손을 이길 것입니다! 꼭짓점의 "터치"여부에 따라 파이프의 색상을 변경할 수 있습니까?
jimbobmcgee 2013

1
파이프 경로를 변경하여 경로를 표시 할 수 있다고 생각합니다. 어떤 연결 (수평) 파이프를 "수행"해야하고 어떤 것을 피해야하는지 결정하는 방법을 잘 모르겠습니다. 현재 모든 연결 파이프는 "열려 있습니다".
DavidC

무작위로 하나를 선택하거나 내가 내 것처럼했던 것처럼 정의 할 수 있습니까? 여전히 이길 것입니다-출력이 너무 예쁘지 않습니다!
jimbobmcgee 2013

1
지금은 같은 수평에 여러 개의 수평 파이프를 사용하는 것 같습니다. 이것이 기본 규칙 # 1을 위반한다고 생각합니다.
Timwi

팀위, 고마워 그 감독이 수정되었습니다.
DavidC

12

씨#

( "C # 프로그램"모드에서 LINQPad를 통해;)

골프가 갈 때까지 Equitable Stroke Control을 적용해야하지만 이것이 C # ( 내가 LINQPad이지만 내 C # 응용 프로그램을 작동시키는 모든 상용구를 원하는 사람은 누구입니까?) 에서 내 접근 방식입니다 .

그리드 정의는 가변적이며 여러 개의 수직 파이프와 전체 구조의 높이를 가지며 시드를 전달하여 반복적으로 무작위입니다 ( PipeGrid생성자 참조 ).

어느 방향 으로든 가능하다면 객체가 어떤 방향으로 흐를 지에 대한 명확한 대답이 없다면, 많은 옵션에서 행동을 지정할 수 있습니다 ( SolveBehavior열거 / PipeSolver생성자 참조 ).

수직 시작은 정의 가능합니다 (참조 PipeSolver.Solve).

수평 파이프는 항상 두 개의 인접한 수직 파이프 사이에 있다고 가정했습니다. 즉, 수평 파이프는 수평 파이프 를 우회 할 수 없습니다.

///<summary>Entry point</summary>
void Main()
{
    var grid = new PipeGrid(vertical:10, height:10, seed:5);
    var solver = new PipeSolver(grid, SolveBehavior.FlipFlop);
    solver.Solve(start:2);
}

///<summary>Represents the direction the object is travelling</summary>
enum Direction
{
    Down = 0,
    Left = 1,
    Right = 2
}

///<summary>Determines the route to take if a junction yields both horizontal directions</summary>
enum SolveBehavior
{
    ///<summary>Throws an <see cref="InvalidOperationException" /></summary>
    Fail = 0,

    ///<summary>Prefers the left-most direction (screen-relative)</summary>
    FavorLeft = 1,

    ///<summary>Prefers the right-most direction (screen-relative)</summary>
    FavorRight = 2,

    ///<summary>Alternates preferred direction, based on the number of turns</summary>
    FlipFlop = 3,

    ///<summary>Prefers the same direction the object travelled, on its last horizontal movement</summary>
    SameDirection = 4,

    ///<summary>Prefers the opposite direction the object travelled, on its last horizontal movement</summary>
    Uturn = 5
}

///<summary>Provides the logic for solving a <see cref="PipeGrid" /></summmary>
class PipeSolver
{
    ///<summary>Creates a new <see cref="PipeSolver" /> for the supplied <paramref name="grid" />,
    ///with the given <paramref name="behavior" /> used to resolve junctions with both horizontal 
    ///paths</summary>
    public PipeSolver(PipeGrid grid, SolveBehavior behavior = SolveBehavior.FlipFlop)
    {       
        if (grid == null) throw new ArgumentNullException("grid");
        _grid = grid;
        _behavior = behavior;
    }

    private readonly PipeGrid _grid;
    private readonly SolveBehavior _behavior;

    ///<summary>Simulate the dropping of an object to run through the grid, at the top of a
    ///given <paramref name="start" /> vertical pipe</summary>
    public void Solve(int start = 1, bool dumpFrames = false, string tag = "Result")
    {
        if (start < 1) start = 1;
        if (start > _grid.Verticals) start = _grid.Verticals;

        int x, y;

        Direction?[,] path = new Direction?[_grid.Width, _grid.Height];

        x = (start - 1) * 2;
        y = 0;
        Direction dir = Direction.Down, lastDir = Direction.Down;

        int turns = 0;      
        do
        {
            path[x, y] = dir;       // we moved through this pipe

            // rule 1: when moving through horizontal pipe, object will go down when possible
            if ((dir == Direction.Left || dir == Direction.Right) && (x % 2 == 0))
            {
                lastDir = dir;
                dir = Direction.Down;
                ++turns;
            }
            // rule 2: when moving through start pipe, object will turn into horizontal pipe when possible
            else if (dir == Direction.Down)
            {
                bool hasLeft  = (x > 0 && _grid[x - 1, y]);
                bool hasRight = (x < _grid.Width - 1 && _grid[x + 1, y]);

                if (hasLeft && hasRight)
                {
                    switch (_behavior)
                    {
                        case SolveBehavior.FavorLeft: 
                            hasRight = false;       // "forget" about right pipe
                            break;
                        case SolveBehavior.FavorRight:
                            hasLeft = false;        // "forget" about left pipe
                            break;
                        case SolveBehavior.FlipFlop:
                            if (turns % 2 == 0) hasLeft = false;
                            else hasRight = false;  // "forget" about left on the even moves, or right on the odd moves
                            break;
                        case SolveBehavior.SameDirection:   // force staying in the same direction
                            if (lastDir == Direction.Left)       hasRight = false;
                            else if (lastDir == Direction.Right) hasLeft = false;
                            else goto case SolveBehavior.FlipFlop;  // use the flip-flop behaviour to determine first turn
                            break;
                        case SolveBehavior.Uturn:   // force turning back on itself
                            if (lastDir == Direction.Left)       hasLeft = false;
                            else if (lastDir == Direction.Right) hasRight = false;
                            else goto case SolveBehavior.FlipFlop;  // use the flip-flop behaviour to determine first turn
                            break;
                        default: throw new InvalidOperationException(
                            "Failed to find distinct path, with no resolving behavior defined"
                        );
                    }
                }

                if (hasLeft)        dir = Direction.Left;
                else if (hasRight)  dir = Direction.Right;

                if (hasLeft || hasRight) ++turns;
            }

            switch (dir)    // update position, based on current direction
            {
                case Direction.Left:  if (x > 0) --x; break;
                case Direction.Right: if (x < _grid.Width - 1) ++x; break;
                default: ++y; break;
            }
            if (dumpFrames) 
            {
                DumpFrame(path, start, tag:string.Concat("Frame #", turns, " (", _grid.Seed, ")"));
                DrawFrame(path, start, tag:string.Concat("Frame #", turns));
            }
        } 
        while (y < _grid.Height);

        int end = (x / 2) + 1;
        DumpFrame(path, start, end, turns, tag);
        DrawFrame(path, start, end, turns, tag);
    }

    ///<summary>Internal method for drawing a given frame</summary>
    private void DumpFrame(Direction?[,] path, int start, int? end = null, int? turns = null, string tag = null)
    {
        var builder = new StringBuilder();

        builder.Append(' ', --start * 5).AppendLine("v");
        for (int y = 0; y < _grid.Height; y++)
        {
            for (int x = 0; x < _grid.Width; x++)
            {
                builder.Append(
                    (x % 2 == 0) 
                        ? path[x, y].HasValue ? ":"    : _grid[x, y] ? "|"    : " "
                        : path[x, y].HasValue ? "====" : _grid[x, y] ? "----" : "    "
                );
            }
            builder.AppendLine();
        }
        if (end.HasValue)   builder.Append(' ', (end.Value - 1) * 5).AppendLine("^");

        if (turns.HasValue) builder.Append(turns.Value)
                                   .Append(" turns were taken to get to ")
                                   .AppendLine(end.HasValue ? "the end." : "this point.");

        builder.ToString().Dump(string.IsNullOrWhiteSpace(tag) ? "Frame" : tag);
    }

    ///<summary>Internal method for rendering a frame as a bitmap</summary>
    private void DrawFrame(Direction?[,] path, int start, int? end = null, int? turns = null, string tag = null)
    {
        using (var sprites = new Sprites())
        using (var canvas = new Bitmap(16 * _grid.Width, 16 * (_grid.Height + 3)))
        using (var graphics = Graphics.FromImage(canvas))
        {
            graphics.FillRectangle(Brushes.Green, 0, 16, 16 * _grid.Width, 16 * _grid.Height);
            _grid.Draw(graphics, sprites, offsetX:0, offsetY:16);

            // draw the start position
            start = (start - 1) * 32;
            graphics.DrawImageUnscaled(sprites.RoadVertical, start, 0);
            graphics.DrawImageUnscaled(sprites.CarVertical,  start, 0);
            graphics.DrawImageUnscaled(sprites.StartFlag,    start, 0);

            // draw the path
            for (int y = 0; y < _grid.Height; y++)
            for (int x = 0; x < _grid.Width;  x++)
            {
                if (path[x, y].HasValue)
                {
                    Image car;

                    switch (path[x, y])
                    {
                        case Direction.Left:
                            // if even, then on a vertical, so turning left; otherwise travelling left
                            car = (x % 2 == 0) ? sprites.CarTurnLeft : sprites.CarLeft;
                            break;
                        case Direction.Right:
                            // if even, then on a vertical, so turning right; otherwise travelling right
                            car = (x % 2 == 0) ? sprites.CarTurnRight: sprites.CarRight;
                            break;
                        default:
                            car = sprites.CarVertical;
                            if (x == 0 && path[x + 1, y].HasValue)                            // far-left and will move right = turn-right
                                car = sprites.CarTurnRight;
                            else if (x == _grid.Width - 1 && path[x - 1, y].HasValue)         // far-right and will move left = turn-left
                                car = sprites.CarTurnLeft;
                            else if (x > 0 && x < _grid.Width - 1)
                            {
                                car = sprites.CarVertical;                                    // if not right or left, then down
                                if (path[x + 1, y].HasValue && !path[x - 1, y].HasValue)      // if came from the left, then turn right
                                    car = sprites.CarTurnRight;
                                else if (path[x - 1, y].HasValue && !path[x + 1, y].HasValue) // if came from the right, then turn left
                                    car = sprites.CarTurnLeft;
                            }
                            break;
                    }

                    graphics.DrawImageUnscaled(car, 16 * x, 16 * (y + 1));
                }
            }

            // draw the end position, if we are at the end
            if (end.HasValue)
            {
                end = (end - 1) * 32;
                graphics.DrawImageUnscaled(sprites.RoadVertical, end.Value, 16 * (_grid.Height + 1));
                graphics.DrawImageUnscaled(sprites.CarVertical,  end.Value, 16 * (_grid.Height + 1));
                graphics.DrawImageUnscaled(sprites.EndFlag,      end.Value, 16 * (_grid.Height + 1));
            }

            if (turns.HasValue) 
            {
                string s = string.Concat(turns.Value, " turns were taken to get to ", 
                                         end.HasValue ? "the end." : "this point.");

                graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
                graphics.DrawString(s, SystemFonts.DefaultFont, Brushes.Black, 0, 16 * (_grid.Height + 2));
            }

            canvas.Dump(tag ?? "Bonus");
        }       
    }
}

///<summary>Represents a configuration of pipes</summary>
class PipeGrid
{
    ///<summary>Creates a new <see cref="PipeGrid" />, of a given <paramref name="height" />
    ///with the given number of <paramref name="vertical" /> pipes, and randomly distributes 
    ///horizontal pipes between them, based on a repeatable <paramref name="seed" />.</summary>
    public PipeGrid(int vertical = 4, int height = 8, int? seed = null)
    {
        if (vertical < 2) vertical = 2;
        if (height < 2) height = 2;

        Width = (2 * vertical) - 1;
        Height = height;
        Verticals = vertical;

        Seed = seed ?? Environment.TickCount;
        var rnd = new Random(Seed);

        _nodes = new bool[Width,Height];
        for (int x = 0, xw = Width; x < xw; x++) 
        for (int y = 0; y < height; y++)
        {
            // place verticals in every even column, and randomly place horizontals in odd columns
            if (x % 2 == 0 || rnd.Next(0, 2) == 1)
                _nodes[x, y] = true;
        }
    }

    private readonly bool[,] _nodes;

    public int Width { get; private set; }
    public int Height { get; private set; }
    public int Verticals { get; private set; }
    public int Seed { get; private set; }

    public bool this[int x, int y] { get { return _nodes[x, y]; } }

    ///<summary>Renders the grid to the LINQPad results pane, for inspection</summary>
    public PipeGrid Dump(string tag = null)
    {
        var builder = new StringBuilder();

        for (int y = 0; y < Height; y++)
        {
            for (int x = 0; x < Width; x++)
            {
                builder.Append(
                    (x % 2 == 0)
                        ? _nodes[x, y] ? "|"    : " "
                        : _nodes[x, y] ? "----" : "    "
                );
            }
            builder.AppendLine();
        }

        builder.ToString().Dump(string.IsNullOrWhiteSpace(tag) ? "Grid" : tag);
        return this;
    }

    ///<summary>Render the grid as a bitmap image</summary>
    public void Draw(Graphics g, Sprites s, int offsetX = 0, int offsetY = 0)
    {           
        for (int y = 0; y < Height; y++)
        {
            for (int x = 0; x < Width; x++)
            {
                if (_nodes[x, y])
                {   
                    Image sprite = sprite = s.RoadVertical;

                    if (x % 2 != 0) 
                        sprite = s.RoadHorizontal;
                    else if (x == 0 && _nodes[1, y])
                        sprite = s.JunctionTeeRight;
                    else if (x == Width - 1 && _nodes[x - 1, y])
                        sprite = s.JunctionTeeLeft;
                    else if (x > 0 && x < Width - 1)
                    {
                        if (_nodes[x - 1, y] && _nodes[x + 1, y])
                            sprite = s.JunctionCross;
                        else if (_nodes[x + 1, y] && !_nodes[x - 1, y])
                            sprite = s.JunctionTeeRight;
                        else if (_nodes[x - 1, y] && !_nodes[x + 1, y])
                            sprite = s.JunctionTeeLeft;
                    }

                    g.DrawImageUnscaled(sprite, 
                                        x:(16 * x) + offsetX, 
                                        y:(16 * y) + offsetY);
                }
            }
        }
    }

    ///<summary>Creates a <see cref="PipeGrid" /> with horizontal pipes at all possible positions</summary>
    public static PipeGrid CreateAllOpen(int verticals = 4, int height = 8)
    {
        var grid = new PipeGrid(verticals, height, 0);
        for (int y = 0; y < height; y++)
        for (int x = 0, xw = grid.Width; x < xw; x++)
            grid._nodes[x, y] = true;

        return grid;
    }
}

///<summary>Store tile sprites, to be used in the graphical rendering of the result</summary>
class Sprites : IDisposable
{
    public Sprites()
    {
        byte[,] car = new byte[,] {
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 },
            { 0, 0, 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0, 0, 0 },
            { 0, 0, 0, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0, 0, 0 },
            { 0, 0, 0, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0, 0, 0 },
            { 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0 },
            { 0, 0, 0, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0, 0, 0 },
            { 0, 0, 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0, 0, 0 },
            { 0, 0, 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0, 0, 0 },
            { 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0 },
            { 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        };
        byte[,] road = new byte[,] {
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
        };
        byte[,] roadNESW = new byte[,] {
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
            { 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6 },
            { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
            { 2, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 2, 2, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 2, 2, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 2, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 2, 2, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 2, 2, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 2, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 2, 2, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 2, 2, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 2, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
            { 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
        };
        byte[,] roadNES = new byte[,] {
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
            { 0, 6, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 0, 6, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 0, 6, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 0, 6, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 0, 6, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 0, 6, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 0, 6, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 0, 6, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 0, 6, 2, 2, 5, 5, 2, 5, 5, 2, 5, 5, 2, 2, 2, 2 },
            { 0, 6, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 2 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6 },
            { 0, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0 },
        };
        byte[,] start = new byte[,] {
            { 0, 0, 1, 1, 1, 0, 4, 4, 4, 0, 0, 0, 4, 0, 0, 0 },
            { 0, 0, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0 },
            { 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0 },
            { 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0 },
            { 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0 },
            { 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0 },
            { 0, 0, 1, 4, 4, 4, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        };
        byte[,] end = new byte[,] {
            { 0, 0, 1, 1, 1, 0, 1, 1, 6, 0, 0, 0, 6, 0, 0, 0 },
            { 0, 0, 1, 6, 6, 6, 1, 1, 6, 6, 1, 1, 6, 0, 0, 0 },
            { 0, 0, 1, 1, 6, 6, 6, 6, 1, 6, 1, 1, 1, 0, 0, 0 },
            { 0, 0, 1, 1, 1, 1, 6, 6, 1, 1, 6, 6, 1, 0, 0, 0 },
            { 0, 0, 1, 1, 1, 1, 1, 1, 6, 1, 6, 6, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 6, 6, 1, 1, 6, 6, 1, 1, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 6, 6, 6, 6, 1, 6, 1, 1, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 1, 1, 6, 6, 1, 1, 6, 6, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 6, 6, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        };

        RoadVertical     = Sprite(road);
        RoadHorizontal   = RotateSprite(RoadVertical, 90);
        JunctionCross    = Sprite(roadNESW);
        JunctionTeeRight = Sprite(roadNES);
        JunctionTeeLeft  = FlipSprite(JunctionTeeRight, horizontal:true);
        CarVertical      = Sprite(car);
        CarLeft          = RotateSprite(CarVertical,  90);
        CarRight         = FlipSprite(CarLeft, horizontal:true);
        CarTurnLeft      = RotateSprite(CarVertical,  45);
        CarTurnRight     = FlipSprite(CarTurnLeft, horizontal:true);
        StartFlag        = Sprite(start);
        EndFlag          = Sprite(end);
    }

    public Image RoadVertical     { get; private set; }
    public Image RoadHorizontal   { get; private set; }
    public Image JunctionCross    { get; private set; }
    public Image JunctionTeeLeft  { get; private set; }
    public Image JunctionTeeRight { get; private set; }
    public Image CarVertical      { get; private set; }
    public Image CarLeft          { get; private set; }
    public Image CarRight         { get; private set; }
    public Image CarTurnLeft      { get; private set; }
    public Image CarTurnRight     { get; private set; }
    public Image StartFlag        { get; private set; }
    public Image EndFlag          { get; private set; }

    ///<summary>Create a sprite from the byte data</summary>
    private Image Sprite(byte[,] data) 
    {
        int width = data.GetLength(0);
        int height = data.GetLength(1);

        var image = new Bitmap(width, height);

        for (int y = 0; y < height; y++)
        for (int x = 0; x < width; x++)
        {
            Color c;
            switch (data[y,x])
            {
                case 1: c = Color.Black; break;
                case 2: c = Color.DarkGray; break;
                case 3: c = Color.Red; break;
                case 4: c = Color.LimeGreen; break;
                case 5: c = Color.Yellow; break;
                case 6: c = Color.White; break;
                default: continue;
            }

            image.SetPixel(x, y, c);
        }

        return image;
    }

    ///<summary>Rotate an image by a number of <paramref name="degrees" /> around the centre</summary>
    private Image RotateSprite(Image source, float deg)
    {
        var b = new Bitmap(source.Width, source.Height);

        using (var g = Graphics.FromImage(b))
        {
            float tx = (float)source.Width / 2.0f;
            float ty = (float)source.Height / 2.0f;

            g.TranslateTransform(tx, ty);
            g.RotateTransform(deg);
            g.TranslateTransform(-tx, -ty);
            g.DrawImageUnscaled(source, 0, 0);
        }

        return b;
    }

    ///<summary>Flip an image about its centre</summary>
    private Image FlipSprite(Image source, bool horizontal = false, bool vertical = false)
    {
        var b = new Bitmap(source);

        RotateFlipType rft = ( horizontal &&  vertical) ? RotateFlipType.RotateNoneFlipXY
                           : ( horizontal && !vertical) ? RotateFlipType.RotateNoneFlipX
                           : (!horizontal &&  vertical) ? RotateFlipType.RotateNoneFlipY
                           : RotateFlipType.RotateNoneFlipNone;

        b.RotateFlip(rft);
        return b;
    }

    #region IDisposable implementation
    public void Dispose() { Dispose(true); }
    ~Sprites() { Dispose(false); }
    protected void Dispose(bool disposing)
    {
        if (disposing)
        {
            GC.SuppressFinalize(this);
            using (RoadVertical) { }    
            using (RoadHorizontal) { }
            using (JunctionCross) { }
            using (JunctionTeeLeft) { }
            using (JunctionTeeRight) { }
            using (CarVertical) { }
            using (CarLeft) { }
            using (CarRight) { }
            using (CarTurnLeft) { }
            using (CarTurnRight) { }
            using (StartFlag) { }
            using (EndFlag) { };
        }
        RoadVertical = null;
        RoadHorizontal = null;
        JunctionCross = null;
        JunctionTeeLeft = null;
        JunctionTeeRight = null;
        CarVertical = null;
        CarLeft = null;
        CarRight = null;
        CarTurnLeft = null;
        CarTurnRight = null;
        StartFlag = null;
        EndFlag = null;
    }
    #endregion
}

최신 정보:

내 평범한 오래된 텍스트 출력을 두려워하는 것은이 인기 컨텍스트에 대한 약간 단조로운 수 있습니다, 나는 확장 버전까지 제공 이미지로 촬영 경로를 그립니다합니다. 나는 그것을 끔찍한 도로 네트워크를 통해 운전하고 바닥에 가려고하지만 자동차로 모델링했지만 세계에서 가장 최악의 GPS를 사용하여 모든 교차점에서 회전해야합니다.

보너스로, '턴'을 더 명확하게 볼 수 있습니다.

즐기세요 -vroom vroom !!

결과 예 :

(세로 : 10, 높이 : 10, 랜덤 시드 : 5, 파이프 시작 : 2, 동작 해결 : FlipFlop}) LINQPad 결과 페이지에 표시된 {vertical : 10, height : 10, seed : 5, start : 2, behaviour : FlipFlop}에 대한 예제 결과


8

씨#

즐거운 시간! :-)

이 코드는 각 파이프의 양쪽 끝에 최소한 직선 파이프가 있는지 확인합니다. 또한 모호한 회전이 없도록합니다.

using System;

namespace Experiment.DownTheDrain
{
    class Program
    {
        static void Main(string[] args)
        {
            var program = new Program();
            program.Width = 19;
            program.Height = 17;
            program.SpanCount = program.Width * program.Height / 4;
            program.Spacing = 3;
            program.Run();
        }

        public int Width { get; set; }
        public int Height { get; set; }
        public int SpanCount { get; set; }
        public int Spacing { get; set; }
        public bool[,] Spans { get; private set; }

        public void Run()
        {
            GenerateSpans();
            DrawPipes();
            var pipe = ReadStartPipe();
            var turns = DrawPath(pipe);
            WriteTurns(turns);
            Console.ReadLine();
        }

        private void GenerateSpans()
        {
            Random random = new Random();
            Spans = new bool[Width, Height];

            int x, y;
            for (int i = 0; i < SpanCount; i++)
            {
                do
                {
                    x = random.Next(Width);
                    y = random.Next(Height);
                }
                while (SpanAt(x - 1, y) || SpanAt(x, y) || SpanAt(x + 1, y));
                Spans[x, y] = true;
            }
        }

        private void DrawPipes()
        {
            const string Junction = "│┤├┼";

            Console.CursorLeft = 0;
            Console.CursorTop = 0;
            DrawLabels();
            for (int y = -1; y <= Height; y++)
            {
                for (int x = 0; x <= Width; x++)
                {
                    Console.Write(Junction[(SpanAt(x-1,y) ? 1 : 0) + (SpanAt(x,y) ? 2 : 0)]);
                    Console.Write(x == Width ? Environment.NewLine : new string(SpanAt(x, y) ? '─' : ' ', Spacing));
                }
            }
            DrawLabels();
        }

        private void DrawLabels()
        {
            for (int x = 0; x <= Width; x++)
                Console.Write("{0}{1}",
                    (char)(x + 65),
                    x == Width ? Environment.NewLine : new string(' ', Spacing)
                );
        }

        private int ReadStartPipe()
        {
            Console.WriteLine();
            Console.Write("Please select a start pipe: ");
            int pipe;
            do
            {
                var key = Console.ReadKey(true);
                pipe = (int)char.ToUpper(key.KeyChar) - 65;
            }
            while (pipe < 0 || pipe > Width);
            Console.WriteLine((char)(pipe + 65));
            return pipe;
        }

        private int DrawPath(int x)
        {
            int turns = 0;
            Console.CursorTop = 1;
            for (int y = -1; y <= Height; y++)
            {
                if (SpanAt(x - 1, y))
                {
                    x--;
                    Console.CursorLeft = x * (Spacing + 1);
                    Console.WriteLine("╔{0}╝", new string('═', Spacing));
                    turns += 2;
                }
                else if (SpanAt(x, y))
                {
                    Console.CursorLeft = x * (Spacing + 1);
                    Console.WriteLine("╚{0}╗", new string('═', Spacing));
                    x++;
                    turns += 2;
                }
                else
                {
                    Console.CursorLeft = x * (Spacing + 1);
                    Console.WriteLine("║");
                }
            }

            return turns;
        }

        private void WriteTurns(int turns)
        {
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("{0} turns taken to reach the bottom.", turns);
        }

        private bool SpanAt(int x, int y)
        {
            return x >= 0
                && x < Width
                && y >= 0
                && y < Height
                && Spans[x, y];
        }
    }
}

산출:

하수구


1
젠장, 나는 또한 상자 그리기 문자를 사용하는 아이디어를 가지고, 당신은 : 그것에 나를 이길
Timwi

또한 모호한 회전으로 파이프를 생성하지 않는 것이 좋습니다. 나는 그것을 생각하지 않았다!
Timwi

8

펀시 턴

Funciton이 이미 세계에서 가장 무의미한 언어가 아닌 것처럼, 이것은 지금까지 내가 작성한 가장 쓸모없는 프로그램입니다.

추가 줄 간격으로 인해 StackExchange에서보기에 좋지 않게 표시되므로 브라우저의 JavaScript 콘솔에서 다음을 실행하여 문제를 해결하십시오.

$('pre').each(function(){$(this).css('line-height',1)})

Funciton에는 난수 생성기가 없으므로 파이프 패턴을 입력하기로 결정했습니다. 패턴 인코딩은 분명하지 않으므로 키보드의 숫자 키를 무작위로 두드리는 것은 난수 생성기만큼 좋습니다.

입력은 공백으로 구분 된 3 개의 10 진수 여야합니다. 첫 번째 숫자는 너비입니다 (수직 파이프 수보다 1이 작음). 두 번째는 시작 파이프의 인덱스이고 마지막은 가로 파이프 패턴을 인코딩하는 숫자입니다. 원하는만큼 크게 만들 수 있습니다. 폭이 음수이거나 파이프 색인이 범위를 벗어난 경우 출력은Impossiburu.

이 프로그램은 자동으로 서로 옆에 두 개의 수평 파이프가 없도록하여 모호한 회전을 유발할 수 있습니다.

                            ┌───╖
               ┌────────────┤ ♯ ╟───────────┬───────────────┐
     ╔════╗  ┌─┴─╖  ┌────╖  ╘═══╝  ╔═══╗  ┌─┴─╖  ╔════╗     │
     ║ 21 ║  │ × ╟──┤ >> ╟─────────╢   ╟──┤ ʘ ╟──╢ 32 ║     │
     ╚═╤══╝  ╘═╤═╝  ╘═╤══╝         ╚═══╝  ╘═══╝  ╚════╝     │
       └───────┘  ┌───┴───┐                                 │
   ╔════╗  ┌───╖  │   ┌───┴──────────────────┐              │
   ║ 32 ╟──┤ ʘ ╟──┘   │          ╔═══╗       │              │
   ╚════╝  ╘═╤═╝    ┌─┴─╖        ║ 0 ╟───┐   │              │
     ┌───────┴──────┤ · ╟────┐   ╚═══╝ ┌─┴─╖ │              │
     │              ╘═╤═╝    └─────────┤ ʃ ╟─┘              │
     │     ┌──────────┘                ╘═╤═╝                │
   ┌─┴─╖ ┌─┴──╖  ┌─────────╖        ┌────┴────╖             │
   │ ♯ ║ │ >> ╟──┤ str→int ╟────┐   │ str→int ║             │
   ╘═╤═╝ ╘═╤══╝  ╘═════════╝  ┌─┴─╖ ╘════╤════╝           ┌─┴─╖
     │   ┌─┴─╖ ╔════╗         │ ░ ║   ┌──┴────────────────┤ · ╟────────────┐
     └───┤ × ╟─╢ 21 ║         ╘═╤═╝ ┌─┴─╖                 ╘═╤═╝            │
         ╘═══╝ ╚════╝┌─────┐    └───┤ ▒ ╟───┐ ┌─────────╖ ┌─┴─╖            │
      ┌─────────╖  ┌─┴─╖   │        ╘═╤═╝   ├─┤ str→int ╟─┤ ʃ ╟─┐          │
   ┌──┤ int→str ╟──┤ · ╟─┐ └──────────┘     │ ╘═════════╝ ╘═╤═╝ │          │
   │  ╘═════════╝  ╘═╤═╝ │ ╔══════════════╗ │ ╔═══╗  ┌──────┘   │          │
   │ ╔══════════╗  ┌─┴─╖ │ ║ 158740358500 ║ │ ║   ╟──┘ ┌───╖  ╔═╧═╗  ┌───╖ │
   │ ║ 20971533 ╟──┤   ╟─┘ ║ 305622435610 ║ │ ╚═══╝  ┌─┤ ≤ ╟──╢ 0 ╟──┤ ≥ ╟─┴─┐
   │ ╚════╤═════╝  └─┬─╜   ║ 491689778976 ║ └────────┤ ╘═╤═╝  ╚═══╝  ╘═╤═╝   │
   │    ┌─┴─╖  ┌───╖ │     ║ 886507240727 ║          │   └──────┬──────┘     │
   │    │ ‼ ╟──┤ ‼ ╟─┘     ║ 896192890374 ║          │         ┌┴┐           │
   │    ╘═╤═╝  ╘═╤═╝       ║ 899130957897 ╟───┐      │         └┬┘           │
   └──────┘    ┌─┴─╖       ╚══════════════╝ ┌─┴─╖  ┌─┴─╖        │            │
               │ ‼ ╟────────────────────────┤ ? ╟──┤ · ╟────────┤            │
               ╘═╤═╝                        ╘═╤═╝  ╘═╤═╝      ┌─┴─╖          │
 ╔═══════════════╧════════════════════════╗   │      └────────┤ ≥ ╟──────────┘
 ║ 83139057126481738391428729850811584337 ║       ┌────╖      ╘═══╝
 ║ 75842912478026089564602018574355013746 ║  ┌────┤ >> ╟──┐
 ║ 85373033606532129933858395805642598753 ║  │    ╘══╤═╝  │
 ║ 19381927245726769973108298347355345088 ║  │     ┌─┴─╖  │       ╓───╖
 ║ 84932603219463911206052446527634696060 ║  │     │ ░ ║  │       ║ ░ ║
 ║ 230797436494578049782495796264992      ║  │     ╘═╤═╝  │       ╙─┬─╜
 ╚════════════════════════════════════════╝  │    ┌──┴──┐ └─────────┴────────┐
                                             │    │   ┌─┴──╖ ┌┐   ┌┐         │
                                             │    │   │ << ╟─┤├─┬─┤├─────┐   │
   ┌────╖  ╔═══╗                             │    │   ╘═╤══╝ └┘ │ └┘   ╔═╧═╗ │
 ┌─┤ << ╟──╢ 1 ║                             │    │   ╔═╧═╗     │      ║ 1 ║ │
 │ ╘═╤══╝  ╚═══╝      ┌───────────────────┐  │    │   ║ 2 ║     │      ╚═╤═╝ │
 │   └─────┬──────────┴─────────┐         │  │ ┌──┴─╖ ╚═══╝   ┌─┴─╖ ┌┐   │   │
 │         │           ┌───┐  ┌─┴─╖       │  │ │ << ╟─────────┤ ? ╟─┤├───┤   │
 │         │           │   ├──┤ · ╟─┐     │  │ ╘══╤═╝         ╘═╤═╝ └┘   ├───┘
 │ ┌───┐ ┌─┴─╖ ┌───╖   └─┬─┘  ╘═╤═╝ ├───┐ │  │  ╔═╧═╗  ╔═══╗  ┌─┴─╖      │
 ├─┤   ├─┤ · ╟─┤ ♯ ╟─────┘    ┌─┴─╖ │   │ │  └──╢ 1 ║  ║ 0 ╟──┤ ? ╟──────┘
 │ └───┘ ╘═╤═╝ ╘═══╝  ┌───────┤ · ╟─┴─┐ │ │     ╚═══╝  ╚═══╝  ╘═╤═╝
 │       ┌─┴─╖      ┌─┴─╖     ╘═╤═╝   │ │ └─────────────────┐   │
 │  ┌────┤ · ╟──────┤ · ╟──┐    │     │ └────────┐          │
 │  │    ╘═╤═╝      ╘═╤═╝  │    │     └────┐     │          │
 │  └───┬──┴──┐       │    │    │        ┌─┴──╖  │          │
 │      │    ┌┴┐      │    │    └─────┬──┤ << ║  │          │
 │      │    └┬┘      │    │         ┌┴┐ ╘═╤══╝  │          │
 │    ┌─┴─╖ ┌─┴─╖   ┌─┴─╖  │         └┬┘ ╔═╧═╗   │          │
 └────┤ · ╟─┤ ? ╟─┐ │ ♯ ║  ├──────────┤  ║ 1 ║   │          │
      ╘═╤═╝ ╘═╤═╝ │ ╘═╤═╝ ┌┴┐         │  ╚═══╝   │          │
        │     │   │ ┌─┴─╖ └┬┘         │          │          │
        │     │   └─┤ ? ╟──┘        ┌─┴─╖        │          │
        │     │     ╘═╤═╝     ┌─────┤ > ╟─────┬──┘          │
        │     │     ┌─┴─╖   ┌─┴─╖   ╘═══╝     ├─────────┐   │
      ┌─┴─╖   └─────┤ · ╟───┤ · ╟─────────────┘         │   │
    ┌─┤ · ╟─────┐   ╘═╤═╝   ╘═╤═╝                       │   │
    │ ╘═╤═╝  ┌──┴─╖ ┌─┴─╖     │                         │   │
    │   │    │ >> ╟─┤ ▒ ╟──┐  ├─────────────┐         ┌─┴─╖ │
    │   │    ╘══╤═╝ ╘═╤═╝  ├──┘             │ ╓───╖ ┌─┤ · ╟─┤
    │   │       │   ┌─┴─╖  │                ├─╢ ▒ ╟─┤ ╘═╤═╝ │
    │   │       └───┤ · ╟──┘                │ ╙─┬─╜ │   │   │
    │   │           ╘═╤═╝                   │   │ ┌─┴─╖ │   │
    │   │           ┌─┴─╖                   │   └─┤ · ╟─┤   │
    │   │        ┌──┤   ╟────────────┐      │     ╘═╤═╝ │   │
    │   │        │  └─┬─╜  ┌───╖   ┌─┴─╖  ┌─┴─╖   ┌─┴─╖ │   │
    │   └──────┐ │    └────┤ ‼ ╟───┤ · ╟──┤ · ╟───┤ ▓ ╟─┘   │
    │          │ │         ╘═╤═╝   ╘═╤═╝  ╘═╤═╝   ╘═╤═╝     │
    │          │ │  ╔═══╗  ┌─┴─╖     │      └───────┘       │
    │          │ └──╢ 0 ╟──┤ ? ╟─┐   │                      │
    │          │    ╚═══╝  ╘═╤═╝ │ ┌─┴─╖                    │
    │ ╔═══╗    │           ┌─┴─╖ ├─┤ · ╟─┐                  │
    │ ║ 2 ║    │      ┌────┤ · ╟─┘ ╘═╤═╝ ├──────────────────┘
    │ ╚═╤═╝    │      │    ╘═╤═╝     │   │
    │ ┌─┴─╖  ┌─┴─╖  ┌─┴─╖  ╔═╧═╕ ┌─┐ │   │
    │ │ + ╟──┤ ? ╟──┤ ? ╟──╢   ├─┴─┘ │   │
    │ ╘═╤═╝  ╘═╤═╝  ╘═╤═╝  ╚═╤═╛     │   │
    │   └──┬───┘    ╔═╧═╗    │       │   │
    │      │        ║ 0 ║            │   │
    │      │        ╚═══╝            │   │
    │      └─────────────────────────┘   │
    └────────────────────────────────────┘        ╓┬──╖
 ┌────────────────────────────────────────────────╫┘▓ ╟────────────┐
 │ ╔═══════════╗        ╔════════════════════╗    ╙─┬─╜            │
 │ ║ 387759291 ║        ║ 385690484238253342 ║      │              │
 │ ║ 565251600 ║    ┌───╢ 839653020379129116 ║      │    ┌────┐    │
 │ ║ 199735775 ║  ┌─┴─╖ ╚════════════════════╝      │    │   ┌┴┐   │
 │ ║ 904933210 ╟──┤ ? ╟────────────────┐            │    │   └┬┘   │
 │ ╚═══════════╝  ╘═╤═╝    ┌──────┐    ├────────────┴────┘  ┌─┴─╖  │
 │ ╔═══════════╗  ┌─┴─╖  ┌─┴─╖  ╔═╧═╗  │  ╔════╗    ╔═══╗   │ ♯ ║  │
 │ ║ 388002680 ╟──┤ ? ╟──┤ ≠ ║  ║ 1 ║  │  ║ 21 ║  ┌─╢ 1 ║   ╘═╤═╝  │
 │ ║ 480495420 ║  ╘═╤═╝  ╘═╤═╝  ╚═══╝  │  ╚═╤══╝  │ ╚═══╝    ┌┴┐   │
 │ ║ 244823142 ║    │      ├───────────┘    │     │          └┬┘   │
 │ ║ 920365396 ║    │    ┌─┴─╖  ┌───╖     ┌─┴──╖  │ ┌────╖  ┌─┴─╖  │
 │ ╚═══════════╝    └────┤ · ╟──┤ ‡ ╟─────┤ >> ║  └─┤ >> ╟──┤ · ╟──┴─┐
 │ ╔═══════════╗ ┌───┐   ╘═╤═╝  ╘═╤═╝     ╘═╤══╝    ╘═╤══╝  ╘═╤═╝    │
 │ ║ 618970314 ╟─┘ ┌─┴─╖ ┌─┘      │         │       ┌─┴─╖     │      │
 │ ║ 790736054 ║ ┌─┤ ? ╟─┴─┐      │         ├───────┤ ▓ ╟─────┘      │
 │ ║ 357861634 ║ │ ╘═╤═╝   │      │     ┌───┘       ╘═╤═╝            │
 │ ╚═══════════╝ │ ┌─┴─╖ ┌─┴─╖  ┌─┴─╖ ┌─┴─╖         ┌─┴─╖     ╔═══╗  │
 │ ╔═══════════╗ │ │ ‼ ╟─┤ · ╟──┤ ? ╟─┤ · ╟─────────┤ · ╟──┐  ║ 1 ║  │
 │ ║ 618970314 ╟─┘ ╘═╤═╝ ╘═╤═╝  ╘═╤═╝ ╘═╤═╝         ╘═╤═╝  │  ╚═╤═╝  │
 │ ║ 790736054 ║     │   ┌─┴─╖  ┌─┴─╖   │   ╓┬──╖    ┌┴┐  ┌┴┐   │    │
 │ ║ 357861713 ║     └───┤ · ╟──┤ · ╟───┘ ┌─╫┘‡ ╟─┐  └┬┘  └┬┘   │    │
 │ ╚═══════════╝         ╘═╤═╝  ╘═╤═╝     │ ╙───╜ │ ┌─┴─╖  └────┤    │
 │ ╔════════════════╗    ┌─┴─╖  ┌─┴─╖     │ ┌───╖ │ │ ♯ ║       └────┘
 │ ║ 43980492383490 ╟────┤ ? ╟──┤ ? ╟───┐ └─┤ ‼ ╟─┘ ╘═╤═╝
 │ ╚════════════════╝    ╘═╤═╝  ╘═╤═╝   │   ╘═╤═╝    ┌┴┐
 │ ╔════════════════╗      │      │     │     │      └┬┘
 │ ║ 43980492383569 ╟──────┘            └──────┬──────┘
 │ ╚════════════════╝                          │
 └─────────────────────────────────────────────┘

설명

  • 메인 프로그램은 처음 두 칸을 찾아 숫자를 나눕니다. 세 번째 (파이프 패턴)를 통과 한 다음 결과 를 호출 하여 출력과 수행 된 회전 수를 반환합니다. 그런 다음 텍스트를 추가합니다 n turns were taken to get to the end.. 여기서 n회전 수는로 계산됩니다 .

  • 숫자를 가져와 01비트 마다 비트를 삽입 하므로 두 개의 수평 파이프가 연속되지 않습니다.

  • 연속적으로 호출 한 다음 파이프 패턴에서 올바른 비트 수를 0이 될 때까지 시프트 하여 출력을 생성합니다 . 또한 "현재 파이프"를 적절하게 늘리거나 줄입니다.

  • 출력의 한 줄을 생성합니다. 각 반복에서 파이프 패턴에서 1 비트 씩 이동 한 다음 출력 (+ 4 공백), (+ 4 공백) ├────┤, ╔════╝또는 ╚════╗; 후자의 경우에는 다음 반복에서 첫 번째 문자를 제거합니다. 마지막 반복은 │\r\n또는 ║\r\n적절하게 생성 합니다.

출력 예

입력:

6 3 73497529294753

산출:

├────┤    │    ║    │    │    │
├────┤    │    ╚════╗    ├────┤
│    ├────┤    ╔════╝    ├────┤
│    ├────┤    ║    │    │    │
│    │    │    ║    │    ├────┤
│    │    │    ║    ├────┤    │
│    ├────┤    ╚════╗    ├────┤
│    ├────┤    │    ║    │    │
│    ├────┤    ╔════╝    │    │
├────┤    ╔════╝    │    ├────┤
│    │    ║    │    │    ├────┤

10 turns were taken to get to the end.

입력:

3 0 65536

산출:

║    │    │    │
║    │    │    │
║    │    ├────┤

0 turns were taken to get to the end.

입력:

3 7 75203587360867 (파이프 인덱스가 범위를 벗어남)

산출:

Impossiburu.

3

그루비, 311

t=System.in.text.collect{it.collect{it}};s=t.size();d=0;c=0;y=0;x=t[0].indexOf('|');println' '*x+'V'
while(y<s){t[y][x]=t[y][x]=='|'?':':'='
if(d){x+=d}else y++
if(y<s)if(d){if(t[y][x]=='|'){d=0;c++}}else if(t[y][x+1]=='-'){d=1;c++} else if(t[y][x-1]=='-'){d=-1;c++}}
t.each{println it.join()}println' '*x+'^'+c
  • 1 행 : 설정 및 처음 찾기 |
  • 2 행 : 교체 교체 : 또는 =
  • 3 행 : x / y를 다음 위치로 이동 (d = 0 = 아래로, d = -1 = 왼쪽, d = 1 = 오른쪽)
  • 4 행 : 다음 방향 찾기
  • 5 행 : 결과 출력

여기 형식이 있습니다.

t=System.in.text.split('\n').collect{it.collect{it}}; s=t.size()
d=0; c=0; y=0; x=t[0].indexOf('|')
println ' '*x + 'V'
while (y<s) { 
    t[y][x] = t[y][x] == '|' ? ':' : '='
    if (d) {x += d} else y++
    if (y<s) 
        if (d) {if (t[y][x]=='|') {d = 0; c++}} 
        else if(t[y][x+1]=='-') {d = 1; c++}
        else if(t[y][x-1]=='-') {d = -1; c++}
}
t.each {println it.join()}
println ' '*x + '^'+c

샘플의 출력 :

V
:       |       |-------|  
:=======:       |-------|  
|       :=======:       |  
|-------|-------:=======:  
|       |-------|       :  
|-------|       :=======:  
|-------|       :=======:  
|       |-------|       :
                        ^10

다른 출력 :

V
:       |       |-------|       |
:=======:       |-------|       |
|       :=======:       |-------|  
|-------|-------:=======:       |
|       |-------|       :=======:
|-------|       |-------|       :
|-------|       |-------|       :
|       |-------|       :=======:
|       |-------|       :       |
|       |       :=======:       |
|-------|       :       |       |
|       :=======:       |       |
|       :       |-------|       |
|       :=======:       |       |
                ^16

(나는 인기 대신 코드 골프를했음을 알고 있지만 그것은 내 스타일 일뿐입니다)


2

자바 스크립트

HTML 캔버스는 클릭 이벤트를 수신하고 가장 가까운 파이프 행을 찾아 시작점으로 사용합니다. 출력은 캔버스에 그려지며 OP에 의해 정의 된 ASCII 출력을 포함하는 텍스트 영역도 있습니다.

이 알고리즘은 두 개의 연결 수평 파이프가 없는지 확인합니다. 이 제한 외에, 확률은 초기 변수에 정의되며 수평 파이프의 발생 여부를 무작위로 결정하는 데 사용됩니다.

JS 피들

<html>
<head>
<script type="text/javascript">
var     WIDTH       = 20,
        HEIGHT      = 15,
        JUNCTIONS   = [],
        PROBABILITY = 0.2,
        COLOR1      = '#00DD00',
        COLOR2      = '#DD0000',
        RADIUS      = 4,
        SPACING     = 20,
        turns       = 0,
        pipe        = 10,
        canvas,
        context;

function Junction( x, y ){
    this.x = x;
    this.y = y;
    this.l = null;
    this.r = null;

    if ( y == 0 )
        JUNCTIONS[x] = [];

    JUNCTIONS[x][y] = this;

    var l = this.left();
    if ( x > 0 && l.l == null && Math.random() <= PROBABILITY )
    {
        this.l = l;
        l.r = this;
    }
}

Junction.prototype.left = function(){
    return this.x == 0?null:JUNCTIONS[this.x-1][this.y];
}
Junction.prototype.right= function(){
    return this.x == WIDTH-1?null:JUNCTIONS[this.x+1][this.y];
}
Junction.prototype.down = function(){
    return this.y == HEIGHT-1?null:JUNCTIONS[this.x][this.y+1];
}
Junction.prototype.reset = function(){
    this.entry = null;
    this.exit = null;
}

Junction.prototype.followPipe = function( prev ){
    this.entry = prev;
    if ( prev === this.l || prev === this.r ) {
        this.exit = this.down() || true;
        turns++;
    } else if ( this.l !== null ) {
        this.exit = this.l;
        turns++;
    } else if ( this.r !== null ) {
        this.exit = this.r;
        turns++;
    } else
        this.exit = this.down() || true;
    console.log( this.exit );
    if ( this.exit !== true )
        this.exit.followPipe( this );
}

Junction.prototype.toString = function(){
    if ( this.entry === null ){
        if ( this.r === null )  return '|  ';
                                        return '|--';
    } else {
        if ( this.r === null )  return ':  ';
                                        return ':==';
    }
}

function init(){
    for ( var x = 0; x < WIDTH; ++x )
        for ( var y = 0; y < HEIGHT; ++y )
            new Junction( x, y );

    canvas  = document.getElementById('canvas');
    context = canvas.getContext('2d');

    canvas.addEventListener('click', draw );

    draw();
}

function draw( evt ){
    for ( var x = 0; x < WIDTH; ++x )
        for ( var y = 0; y < HEIGHT; ++y )
            JUNCTIONS[x][y].reset();

    if ( evt ){ 
        pipe = Math.round((evt.clientX - canvas.getBoundingClientRect().left)/SPACING)-1;
        if ( pipe < 0 )     pipe = 0;
        if ( pipe >= WIDTH )    pipe = WIDTH - 1;
    }

    turns = 0;
    JUNCTIONS[pipe][0].followPipe( true );

    context.clearRect(0, 0, canvas.width, canvas.height);
    context.lineWidth = 2;

    for ( var y = 0; y < HEIGHT; ++y ) {
        for ( var x = 0; x < WIDTH; ++x ) {
            var j = JUNCTIONS[x][y];
                    e = j.entry;

            if ( j.r !== null ){
                context.beginPath();
                context.strokeStyle = e===null?COLOR1:COLOR2;
                context.moveTo(SPACING*(x+1), SPACING*(y+1));
                context.lineTo(SPACING*(x+2), SPACING*(y+1));
                context.stroke();
            }

            if ( y > 0 ){
                context.beginPath();
                context.strokeStyle = (e===JUNCTIONS[x][y-1])?COLOR2:COLOR1;
                context.moveTo(SPACING*(x+1), SPACING*(y));
                context.lineTo(SPACING*(x+1), SPACING*(y+1));
                context.stroke();
            }
        }
    }

    for ( var y = 0; y < HEIGHT; ++y ) {
        for ( var x = 0; x < WIDTH; ++x ) {
            context.beginPath();
            context.arc(SPACING*(x+1), SPACING*(y+1), RADIUS, 0, 2*Math.PI, false);
            context.fillStyle = JUNCTIONS[x][y].entry===null?COLOR1:COLOR2;
            context.fill();
        }
    }

    var h = [];
    for ( var x = 0; x < WIDTH; ++x )
        h.push( x!=pipe?'   ':'v  ' );
    h.push( '\n' );
    for ( var y = 0; y < HEIGHT; ++y ) {
        for ( var x = 0; x < WIDTH; ++x )
            h.push( JUNCTIONS[x][y].toString() )
        h.push( '\n' );
    }
    for ( var x = 0; x < WIDTH; ++x )
        h.push( JUNCTIONS[x][HEIGHT-1].exit!==true?'   ':'^  ' );
    h.push( '\n' );
    h.push( turns + ' turns were taken to get to the end.' );
    document.getElementById( 'output' ).value = h.join( '' );
}

window.onload   = init;
</script>
</head>
<body>
<p>Click on a row to show the path</p>
<canvas id="canvas" width="450" height="350"></canvas>
<textarea id="output" style="width:100%; height:24em;"></textarea>
</body>
</html>

산출

http://imageshack.com/a/img600/9241/94wh.png

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.