冰高尔夫挑战赛


24

这项挑战的目标是编写一个程序或函数,以返回完成给定课程所需的最少罢工量。

输入项

  • 课程的布局可以采用您喜欢的任何合适方式和格式。(从控制台读取,作为输入参数传递,从文件或任何其他多行字符串,字符串数组,二维字符/字节数组读取)。
  • 球的起始位置和球洞也可以作为输入传递,不必从输入中解析。在测试用例中,它们包含在课程中,以确保对实际位置没有混淆。
  • 您可以将输入字符重新映射到其他字符,只要它们仍可识别为不同的字符(例如,可打印的ASCII字符)。

输出量

  • 对于以合理格式(字符串,整数,浮点数或描述结果的ku句)作为输入传递的任何路线,程序必须返回最低的得分(到达空洞所需的最少击球次数)
  • 如果该课程无法克服,则返回-1(或您选择的其他任何不正确的值,对于可击败的课程都不会返回)。

例:

在此示例中,位置以从0开始,X / Y,从左到右,自上而下的方式标记-但是您可以使用任何喜欢的格式,因为结果无论如何都与格式完全无关。

输入:

###########
#     ....# 
#      ...# 
#  ~    . # 
# ~~~   . # 
# ~~~~    # 
# ~~~~    # 
# ~~~~  o # 
# ~~~~    # 
#@~~~~    # 
###########

Ball (Start-Position): 1/9
Hole (End-Position):   8/7

输出:

8

示例课程

规则和领域

该课程可以包含以下领域:

  • '@' -课程开始
  • 'o' Hole-课程目标
  • '#' -碰到墙时球将停止
  • '~' -必须避免
  • '.' -球会立即停在沙上
  • ' ' -球将继续滑动直到碰到东西

游戏的基本规则和限制:

  • 球不能对角移动,只能向左,向右,向上和向下移动。
  • 球不会停在水面,只会停在墙前,沙地和洞中。
    • 射入水中是无效的/不可能的
    • 球会留在洞中,不会像在冰上那样跳过它
  • 路线始终为矩形。
  • 路线始终被水或墙壁包围(无需边界检查)。
  • 总有一个球和一个洞。
  • 并非所有课程都可以打败。
  • 可能有多个路径导致相同(最低)分数。

漏洞和获胜条件

  • 禁止出现标准漏洞
  • 程序必须终止
  • 您无法制定其他规则(很难击中球,以至于跳过水面,从墙反弹,越过沙田,拐角处弯曲等等)
  • 这是,所以用最少字符数的解决方案获胜。
  • 解决方案必须能够处理所有提供的测试用例,如果由于所用语言的限制而无法实现,请在答案中注明。

测试用例

路线1(2次打击)

####
# @#
#o~#
####

课程2(不可能)

#####
#@  #
# o #
#   #
#####

路线#3(3击)

~~~
~@~
~.~
~ ~
~ ~
~ ~
~ ~
~.~
~o~
~~~

路线#4(2次打击)

#########
#~~~~~~~#
#~~~@~~~#
##  .  ##
#~ ~ ~ ~#
#~. o .~#
#~~~ ~~~#
#~~~~~~~#
#########

课程5(不可能)

~~~~~~~
~...  ~
~.@.~.~
~...  ~
~ ~ ~.~
~ . .o~
~~~~~~~

更多测试用例:

https://pastebin.com/Azdyym00


1
相关:
AdmBorkBork

如果我们使用二维字节数组作为输入,是否允许对符号使用自定义映射?
Arnauld

@Arnauld不知道在这方面通常达成的共识是什么,但是我想说只要确定输入仍然可以。我已经更新了输入部分。
Manfred Radlwimmer

如果直接输入目的地,我们可以要求目的地的位置是“ sand”符号吗?
l4m2

@ l4m2当然可以,它将与所有其他规则保持一致。
Manfred Radlwimmer

Answers:


6

JavaScript(ES6),174个字节

curling currying语法接受输入([x, y])(a),其中xy是起始位置的0索引坐标,而a []是整数矩阵,其中0=冰,1=墙,2=沙,3=孔和4=水

0如果没有解决方案,则返回。

p=>a=>(r=F=([x,y],n,R=a[y],c=R[x])=>R[c&(R[x]=4)|n>=r||[-1,0,1,2].map(d=>(g=_=>(k=a[v=Y,Y+=d%2][h=X,X+=~-d%2])||g())(X=x,Y=y)>3?0:k>2?r=-~n:F(k>1?[X,Y]:[h,v],-~n)),x]=c)(p)|r

在线尝试!

已评论

p => a => (                       // given the starting position p[] and the matrix a[]
  r =                             // r = best result, initialized to a non-numeric value
  F = (                           // F = recursive function taking:
    [x, y],                       //   (x, y) = current position
    n,                            //   n = number of shots, initially undefined
    R = a[y],                     //   R = current row in the matrix
    c = R[x]                      //   c = value of the current cell
  ) =>                            //
    R[                            // this will update R[x] once the inner code is executed
      c & (R[x] = 4) |            //   set the current cell to 4 (water); abort if it was
      n >= r ||                   //   already set to 4 or n is greater than or equal to r
      [-1, 0, 1, 2].map(d =>      //   otherwise, for each direction d:
        (g = _ => (               //     g = recursive function performing the shot by
          k = a[                  //         saving a backup (h, v) of (X, Y)
            v = Y, Y += d % 2][   //         and updating (X, Y) until we reach a cell
            h = X, X += ~-d % 2]) //         whose value k is not 0 (ice)
          || g()                  //   
        )(X = x, Y = y)           //     initial call to g() with (X, Y) = (x, y)
        > 3 ?                     //     if k = 4 (water -> fail):
          0                       //       abort immediately
        :                         //     else:
          k > 2 ?                 //       if k = 3 (hole -> success):
            r = -~n               //         set r to n + 1
          :                       //       else:
            F(                    //         do a recursive call to F():
              k > 1 ?             //           if k = 2 (sand):
                [X, Y]            //             start the next shots from the last cell
              :                   //           else (wall):
                [h, v],           //             start from the last ice cell
              -~n                 //           increment the number of shots
            )                     //         end of recursive call
      ), x                        //   end of map(); x = actual index used to access R[]
    ] = c                         // restore the value of the current cell to c
)(p) | r                          // initial call to F() at the starting position; return r

5

Python 3,273字节

def p(g,c,d,k=0):
	while 1>k:c+=d;k=g.get(c,9)
	return-(k==2)or c-d*(k==3)
def f(g):
	c={q for q in g if g.get(q,9)>4};I=0;s=[c]
	while all(g.get(q,9)-4for q in c):
		c={k for k in{p(g,k,1j**q)for k in c for q in range(4)}if-~k}
		if c in s:return-1
		s+=[c];I+=1
	return I

在线尝试!

-41字节归功于ovs
-1字节归功于Jonathan Frech


难道if k+1不是if-~k
乔纳森·弗雷希

@JonathanFrech是的,谢谢
HyperNeutrino

2

C#,461418字节

这只是(希望)复兴这一挑战的非竞争性参考实现:

凯文·克鲁伊森(Kevin Cruijssen)打高尔夫球

int P(string[]C){int w=C[0].Length,i=0,l=c.Length;var c=string.Join("",C);var h=new int[l];for(var n=new List<int>();i<l;n.Add(i++))h[i]=c[i]!='@'?int.MaxValue:0;for(i=1;;i++){var t=n;n=new List<int>();foreach(int x in t){foreach(int d in new[]{-1,1,-w,w}){for(int j=x+d;c[j]==' ';j+=d);if(c[j]=='#'&h[j-d]>s){h[j-d]=s;n.Add(j-d);}if(c[j]=='.'&h[j]>s){h[j]=s;n.Add(j);}if(c[j]=='o')return s;}}if(n.Count<1)return -1;}}

不打高尔夫球

int IceGolf(string[] course)
{
    // Width of the course
    int w = course[0].Length;

    // Course as single string
    var c = string.Join("", course);

    // Array of hits per field
    var hits = new int[c.Length];

    // Fields to continue from
    var nextRound = new List<int>();

    // Initialize hits
    for (int i = 0; i < hits.Length; i++)
    {
        if (c[i] != '@')
            // All fields start with a high value
            hits[i] = Int32.MaxValue;
        else
        {
            // Puck field starts with 0
            hits[i] = 0;
            nextRound.Add(i);
        }
    }

    for (int s = 1; ; s++)
    {
        // clear the fields that will be used in the next iteration
        var thisRound = nextRound;
        nextRound = new List<int>();

        foreach (int i in thisRound)
        {
            // test all 4 directions
            foreach (int d in new[] { -1, 1, -w, w })
            {
                int j = i+d;

                // ICE - slide along
                while (c[j] == ' ')
                    j += d;

                // WALL - stop on previous field
                if (c[j] == '#' && hits[j-d] > s)
                {
                    hits[j-d] = s;
                    nextRound.Add(j-d);
                }

                // SAND - stop
                if (c[j] == '.' && hits[j] > s)
                {
                    hits[j] = s;
                    nextRound.Add(j);
                }

                // HOLE return strikes
                if (c[j] == 'o')
                    return s;
            }
        }

        // No possible path found
        if (nextRound.Count == 0)
            return -1;
    }
}

在线尝试


1
打了些球:int P(string[]C){int w=C[0].Length,i=0,l=c.Length;var c=string.Join("",C);var h=new int[l];for(var n=new List<int>();i<l;n.Add(i++))h[i]=c[i]!='@'?int.MaxValue:0;for(i=1;;i++){var t=n;n=new List<int>();foreach(int x in t){foreach(int d in new[]{-1,1,-w,w}){for(int j=x+d;c[j]==' ';j+=d);if(c[j]=='#'&h[j-d]>s){h[j-d]=s;n.Add(j-d);}if(c[j]=='.'&h[j]>s){h[j]=s;n.Add(j);}if(c[j]=='o')return s;}}if(n.Count<1)return -1;}}(418字节)。另外,您是否可以添加带有测试代码的TIO链接
凯文·克鲁伊森

感谢您的TIO链接。我上面提供的代码无法正常工作,因此我将其修复,并打了另外三个字节。在线尝试415字节(您必须从当前的TIO重新添加巨大的测试用例。由于该测试用例的链接太大,因此我无法在该注释中粘贴该链接。; p)
Kevin Cruijssen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.