Ruby on Rails(或Trackety Track)


48

您是铁路工程师Ruby。您的任务是在任何给定的山谷中追踪,以使其到达每个站点(M)。铺设的轨道数量并不重要,但必须以一条连续的路径铺设,该路径从山谷的入口/出口点(>)开始和结束,并且在任何一点都不会交叉。还有其他一些限制:mountains(^)是不可逾越的,因此您必须绕过它们,~必须使用bridge(X)穿越rivers (),并且山谷(#)的边缘也是不可实现的。

赛道规则

如果轨道放置不正确,将会出轨,没人会想要,所以这是轨道放置的规则。

轨道有四种:- | / \
以下是每个人如何与其他人结合的方法:

允许的组合来自-(在每个示例的中心):

#####  #####  #####  #####  #####  #####  #####
#   #  #   #  #\  #  #   #  #  /#  #\ /#  #   #
#---#  # --#  # --#  #-- #  #-- #  # - #  # - #
#   #  #/  #  #   #  #  \#  #   #  #   #  #/ \#
#####  #####  #####  #####  #####  #####  #####

-可能永远不会与结合|。这对于火车安全转弯来说太陡了。

允许的组合来自/(在每个示例的中心):

#####  #####  #####  #####  #####  #####  #####
#  /#  #  -#  #  |#  #  /#  #  /#  #  -#  #  |#
# / #  # / #  # / #  # / #  # / #  # / #  # / #
#/  #  #/  #  #/  #  #|  #  #-  #  #|  #  #-  #
#####  #####  #####  #####  #####  #####  #####

\可能永远不会与结合/。这对于火车安全转弯来说太陡了。

允许的组合来自\(在每个示例的中心):

#####  #####  #####  #####  #####  #####  #####
#\  #  #-  #  #|  #  #\  #  #\  #  #-  #  #|  #
# \ #  # \ #  # \ #  # \ #  # \ #  # \ #  # \ #
#  \#  #  \#  #  \#  #  |#  #  -#  #  |#  #  -#
#####  #####  #####  #####  #####  #####  #####

允许的组合来自|(在每个示例的中心):

#####  #####  #####  #####  #####  #####  #####
# | #  #\  #  #  /#  # | #  # | #  #  /#  #\  #
# | #  # | #  # | #  # | #  # | #  # | #  # | #
# | #  # | #  # | #  #/  #  #  \#  #  \#  #/  #
#####  #####  #####  #####  #####  #####  #####

轨道可以通过以下方式与车站,桥梁和山谷入口/出口结合:

#####  #####  #####
#\|/#  #\|/#  #/  #
#-M-#  #-X-#  >-  #
#/|\#  #/|\#  #\  #
#####  #####  #####

车站有转台,因此可以以一个陡峭的角度离开车站(尽管不会退缩,因为您不想撞到另一班来回的预定火车!)。
桥梁用于穿越河流,因此您必须在进入河流的另一侧退出桥梁。

输入项

输入将通过STDIN用于程序,或者通过函数参数用于函数。如果您的函数需要一个名称以便我在输入中运行它,则该名称声明应包括在字节数中。

输入将是带有换行符的单个字符串。输入中的每一行将始终与其他行具有相同的长度,从而为您提供矩形输入。输入的边缘#除进入点外始终是实心和不可逾越的()。任何给定的输入将至少有一个有效答案。

输出量

您的输出应以一个带有换行符的单个字符串形式返回,或者应将其打印/回显到完整程序的屏幕上。

输出应与输入相同,但要添加轨道字符。

计分

优胜者将是最短的代码(以字节为单位)。

测试用例

###########
#    M    #
#   ^     #
>  ^^  M  #
#    ^    #
#~~~~~~~~~#
# M       #
#     ^^  #
#        M#
###########


#################
#               #
#   M         M #
#       ^       #
#        ^ M    #
#~~~~~~~^       #
#               #
#   ^           #
#   M^          #
#    ^          #
> ^^^          M#
#               #
#        M      #
#################

###############
# M   ~       #
#     ~       #
>     ~    M  #
#     ~       #
#     ~       #
#     ~       #
###############

测试用例的可能解决方案

###########
# ---M    #
#/  ^ \   #
>  ^^  M  #
#\   ^ |  #
#~X~~~~X~~#
# M     \ #
#  \  ^^ |#
#   -----M#
###########

#################
#               #
#   M---------M #
#   |   ^    /  #
#  /     ^ M-   #
#~X~~~~~^  |    #
# |         \   #
#  \^        \  #
# --M^        \ #
#/   ^         |#
> ^^^          M#
#\            / #
# -------M----  #
#################

###############
# M   ~       #
#/ \  ~       #
>   --X----M  #
#\    ~    |  #
# \   ~   /   #
#  ---X---    #
###############

8
最后!挑战永远存在于沙盒中!
mbomb007'2013/

18
@ mbomb007不太正确,从此站点开始到在沙箱中发布问题之间有4个月的时间;-)
Gareth

1
@Gareth他们可以转弯吗?它们可以比一个细胞宽吗?
马丁·恩德

1
等待-如果我们在水平移动时需要垂直移动一个空间怎么办?
SIGSTACKFAULT

1
我头疼。我一直在努力,这很困难
Christopher

Answers:


26

Python 2中3990 3430 4412 4313个字节

这基本上是一个带有丑陋的启发式和丑陋getChildren方法的A * 。要连续运行3个测试用例,需要6.5s在我的计算机上进行。该功能f是这里的解决方案。它以地图为字符串,并以字符串形式返回已求解的地图。

from itertools import*
import sys
from Queue import*
A,B,C,D,E,F,G=">|\\/-MX";H=range;I=permutations;J=set;K=abs;L=len
class M:
	@staticmethod
	def T(a):return a in">|\\/-MX"
	@staticmethod
	def C(a,b,c,d,x,y,e):
		if not M.T(d)or not M.T(e):return 0
		if e in"MX"and d in"MX"and e!=d:return 1
		if d==A:return x>0 and(e==D and y==-1 or e==E and y==0 or e==C and y==1)
		if d==F:return e==C and K(x+y)==2 or e==D and x+y==0 or e==B and x==0 or e==E and y==0
		if d==G:
			if b!=0!=c and K(b-x)+K(c-y)==1:return 0
			return e==C and K(x+y)==2 or e==D and x+y==0 or e==B and x==0 or e==E and y==0
		if e!=""and e in"MX>"and a!=""and a in"MX>":return M.C("",0,0,a,-b,-c,d)and M.C("",0,0,e,-x,-y,d)
		elif e!=""and e in"MX>"and a!="":return M.C("",0,0,d,b,c,a)and M.C("",0,0,e,-x,-y,d)
		elif e!=""and e in"MX>"and a=="":return M.C("",0,0,e,-x,-y,d)
		elif a!=""and a in"MX>":return M.C("",0,0,a,-b,-c,d)and M.C("",0,0,d,x,y,e)
		f=[[E,-1,0,E,1,0,E],[D,-1,1,E,1,0,E],[C,-1,-1,E,1,0,E],[E,-1,0,E,1,1,C],[E,-1,0,E,1,-1,D],[C,-1,-1,E,1,-1,D],[D,-1,1,E,1,1,C],[D,-1,1,D,1,-1,D],[D,-1,1,D,1,-1,E],[D,-1,1,D,1,-1,B],[B,-1,1,D,1,-1,D],[E,-1,1,D,1,-1,D],[B,-1,1,D,1,-1,E],[E,-1,1,D,1,-1,B],[C,-1,-1,C,1,1,C],[C,-1,-1,C,1,1,E],[C,-1,-1,C,1,1,B],[B,-1,-1,C,1,1,C],[E,-1,-1,C,1,1,C],[B,-1,-1,C,1,1,E],[E,-1,-1,C,1,1,B],[B,0,-1,B,0,1,B],[C,-1,-1,B,0,1,B],[D,1,-1,B,0,1,B],[B,0,-1,B,-1,1,D],[B,0,-1,B,1,1,C],[D,1,-1,B,1,1,C],[C,-1,-1,B,-1,1,D]];g=0;h=[a,b,c,d,x,y,e];j=[0,3][a==""]
		for k in f:
			l=1;m=1;n=[k[6],k[4],k[5],k[3],k[1],k[2],k[0]]
			for i in H(j,L(k)):
				if k[i]!=h[i]:l=0
				if n[i]!=h[i]:m=0
			if l or m:g=1
		return g
	def __init__(s,a):s.m=[list(x)for x in a.split("\n")]
	def __str__(s):return"\n".join(["".join(x)for x in s.m])
	def A(s):return str(s)
	def B(s):return L(s.m[0])
	def D(s):return L(s.m)
	def E(s):
		a=[]
		for y in H(1,s.D()-1):
			for x in H(1,s.B()-1):
				if s.J(x,y)==F and L(s.H(x,y, F))==0:a+=[(x,y)]
		return a
	def F(s):
		for y in H(s.D()):
			for x in H(s.B()):
				if s.J(x,y)==A:return(x,y)
	def G(s):
		a=0
		for y in H(0,s.D()-1):
			for x in H(0,s.B()-1):
				b=s.J(x,y)
				c=L(s.H(x,y,b))
				if b==A:
					if c==0:a=(x,y)
					c=0
				if c==1:return(x,y)
		if a!=0:
			return a
		raise ValueError()
	def J(s,x,y):return s.m[y][x]
	def K(s,x,y,b):
		a=[[i for i in row]for row in s.m];a[y][x]=b
		return"\n".join("".join(x)for x in a)
	def H(s,x,y,c):
		d=[];e=[]
		for a,b in J(I([-1,-1,0,1,1],2)):
			g=s.J(x+a,y+b)
			if M.T(g)and M.C("",0,0,c,a,b,g):e+=[[g,a,b]]
		if L(e)==1:return[e[0][0]]
		if L(e)==0:return[]
		for g,h in I(e,2):
			i,j,k=g;l,m,n=h;o=x + m;p=y + n
			if M.C(i,j,k,c,m,n,l):
				if l==F:
					if L(s.H(o,p,l))>=1:d+=[l]
				else:d+=[l]
		return d
	def I(s,x,y,a,b):
		if a==0 or b==0:return 0
		a=s.J(x+a,y);b=s.J(x,y+b)
		return(M.T(a)or a==F)and(M.T(b)or b==F)
class P:
	@staticmethod
	def A(x0,y0,x1,y1):return K(x0-x1)+4*K(y0-y1)
	def __init__(s,a,p,t=0,g=0):
		s.a=[];s.b=p;s.c=a;s.d=[a];s.e=t;s.f=g
		if p:s.d=p.d[:];s.d+=[a];s.e=p.e;s.f=p.f
		s.g=M(a);s.h=s.B()
	def __str__(s):return s.g.A()
	def B(s):
		a=0;b=1;c=0
		try:c=s.g.G()
		except:a=1
		d=s.g.E();e=s.g.F();g=[]
		if L(d)==0 and not a:g=P.A(c[0],c[1],e[0],e[1])+b
		elif L(d)==0 and a:return 0
		elif c:
			h,i=c
			for j in combinations(d,L(d)):
				k=0
				for x,y in j:k+=P.A(h,i,x,y);h,i=x,y
				g+=[k]
			g=min(g);g+=s.g.B()+s.g.D()+b
		else:return sys.maxint
		if g<1:return 0
		return g
	def C(s):
		try:a=s.g.G()
		except:s.a=[];return
		b=s.g.J(a[0],a[1]);c=("",0,0);e=(0,0)
		for x,y in J(I([-1,-1,0,1,1],2)):
			g,h=a[0]+x,a[1]+y;i=s.g.J(g,h)
			if M.T(i)and M.C("",0,0,i,x,y,b):c=(i,x,y)
			if i=="~":e=(x,y)
		for x,y in J(I([-1,-1,0,1,1],2)):
			g,h=a[0]+x,a[1]+y;i=s.g.J(g,h)
			if not(i in"^#"or M.T(i)):
				for j in"-|\\/":
					if i=="~":
						j=G 
						if c[0]==G:continue
					if c[0]==G and K(e[0])==1 and y==c[1]:continue
					if c[0]==G and K(e[1])==1 and x==c[0]:continue
					k=s.g.H(g,h,j);l=L(k)
					if(l==1 or l==2 and A in k)and M.C(c[0],c[1],c[2],b,x,y,j)and not s.g.I(a[0],a[1],x,y):
						try:s.a+=[P(s.g.K(g,h,j),s)]
						except:pass
def f(x):
	d=[];a=[];b=PriorityQueue();b.put((0,P(x,0)))
	while not d and b.qsize():
		c=b.get()[1];c.C();a+=[c.c]
		for e in c.a:
			if e.c not in a:
				if not e.h:d=e.d
				b.put((e.h,e))
	return d[-1]

在线尝试!

测试用例

测试1

在此处输入图片说明

###########
# ---M    #
#/  ^ \   #
>  ^^  M  #
#\   ^ |  #
#~X~~~~X~~#
# M    |  #
#  \  ^^\ #
#   -----M#
###########

测试2

在此处输入图片说明

#################
#               #
#   M---------M #
#  /    ^    /  #
# |      ^ M-   #
#~X~~~~~^   \   #
# |          |  #
#  \^        |  #
# --M^       |  #
#/   ^-       \ #
> ^^^/ \       M#
#\  /   \     / #
# --     M----  #
#################

测试3

在此处输入图片说明

###############
# M   ~       #
#/ \  ~       #
>   --X----M  #
#\    ~   /   #
# ----X---    #
#     ~       #
###############

源代码

A *状态+ A *求解器类

我实际上是出于解决方案而打高尔夫球的。但是它们存在于我的“可读”版本中。State类是通用类,可以实现。Solver类采用开始状态,然后跟随该状态进行启发式操作getDist

from Queue import PriorityQueue

# A* State
class State(object):
    # The type of value should be a primative
    def __init__(self, value, parent, start=0, goal=0):
        self.children = []
        self.parent = parent
        self.value = value
        self.dist = 0
        if parent:
            self.path = parent.path[:]
            self.path.append(value)
            self.start = parent.start
            self.goal = parent.goal
        else:
            self.path = [value]
            self.start = start
            self.goal = goal

    # Implement a heuristic for calculating the distance from this state to the goal
    def getDist(self):
        pass

    # Implement a way to create children for this state
    def createChildren(self):
        pass

# A* Solver 
# Note: if maxmin = 1: Solver tries to minimize the distance
#       if maxmin = -1: Solver tries to maximize the distance
class AStar_Solver:
    def __init__(self,startState,maxmin=1):
        self.path = []
        self.visitedQueue = []
        self.priorityQueue = PriorityQueue()
        self.priorityQueue.put((0,startState))
        self.startState = startState
        self.maxmin = maxmin
        self.count = 0

    # Create a png of the string 'qPop'
    def imager(self,qPop):
        # Imager(qPop,str(self.count).rjust(5,"0")+".png")
        # print str(qPop)+"\n"
        self.count += 1

    # Solve the puzzle
    def solve(self):
        while(not self.path and self.priorityQueue.qsize()):
            closestChild = self.priorityQueue.get()[1]
            self.imager(str(closestChild))
            closestChild.createChildren()
            self.visitedQueue.append(closestChild.value)
            for child in closestChild.children:
                if child.value not in self.visitedQueue:
                    if not child.dist:
                        self.imager(str(child))
                        self.path = child.path
                        break
                    self.priorityQueue.put((self.maxmin*child.dist,child))
        if not self.path:
            print "Goal was not reachable"
        return self.path

州级

这是A *状态类的实现。这里最重要的方法是getDist,它是确定离self目标有多接近的启发式方法。从根本上来说,这是访问所有其他目的地并重新开始的最小距离。

from A_Star import State,AStar_Solver
from Ruby_Map import Map
from itertools import combinations, permutations
import sys

# A state class designed to work with A*
class State_Pathfinder(State):

    # This is deprecated
    @staticmethod
    def toValue(location):
        return str(location[0])+","+str(location[1])

    # Calculate the weighted distance between 2 points.
    # Not sure why the deltaY is more weighted. My theory
    # is that it is because the starting point is always
    # on a side. So vertical space is most precious?
    @staticmethod
    def distance(x0,y0,x1,y1):
        # return (abs(x0-x1)**2+abs(y0-y1)**2)**.5
        return 1*abs(x0-x1)+4*abs(y0-y1)

    def __init__(self, maps, parent, value=0, start=0, goal=0):
        super(State_Pathfinder,self).__init__(maps,parent,start,goal)
        self.map = Map(maps)
        self.dist = self.getDist()
        if not value:
            location = self.map.getLocation()
            self.value = maps
            self.path = [self.value]

    def __str__(self):
        return self.map.getDisplay()

    # The heuristic function that tells us
    # how far we are from the goal
    def getDist(self):
        blownup = False
        WEIGHT = 1
        location = None
        try:
            location = self.map.getLocation()
        except ValueError as e:
            blownup = True
        destinations = self.map.getDestinations()
        goal = self.map.getGoal()
        dist = []
        if len(destinations) == 0 and not blownup:
            dist = State_Pathfinder.distance(location[0],location[1],goal[0],goal[1])+WEIGHT
        elif len(destinations) == 0 and blownup:
            return 0
        elif location:
            oldX,oldY = location
            for path in combinations(destinations,len(destinations)):
                length = 0
                for pair in path:
                    x,y = pair
                    length += State_Pathfinder.distance(oldX,oldY,x,y)
                    oldX,oldY = x,y
                dist.append(length)
            dist = min(dist)
            dist += self.map.getWidth()+self.map.getHeight()+WEIGHT
        else:
            return sys.maxint
        if dist<1:
            return 0
        return dist

    # Creates all possible (legal) child states of this state
    def createChildren(self):
        if not self.children:
            try:
                location = self.map.getLocation()
            except:
                self.children = []
                return
            track = self.map.get(location[0],location[1])
            intrack = ("",0,0)
            river = (0,0)
            for x,y in set(permutations([-1,-1,0,1,1],2)):
                realX,realY = location[0]+x,location[1]+y
                adjacent = self.map.get(realX,realY)
                if Map.isTrack(adjacent) and Map.isConnected("",0,0,adjacent,x,y,track):
                    intrack = (adjacent,x,y)
                if adjacent=="~":
                    river = (x,y)
            for x,y in set(permutations([-1,-1,0,1,1],2)):
                realX,realY = location[0]+x,location[1]+y
                adjacent = self.map.get(realX,realY)
                if not Map.isBlocking(adjacent) and not adjacent in "M":
                    for outtrack in "-|\\/":
                        if adjacent=="~":
                            outtrack="X"
                            if intrack[0]=="X":continue
                        if intrack[0]=="X" and abs(river[0])==1 and y==intrack[1]:continue
                        if intrack[0]=="X" and abs(river[1])==1 and x==intrack[0]:continue
                        connections = self.map.getConnections(realX,realY,outtrack)
                        hoppin = len(connections)
                        connected = Map.isConnected(intrack[0],intrack[1],intrack[2],track,x,y,outtrack)
                        blocked = self.map.isBlocked(location[0],location[1],x,y)
                        if (hoppin==1 or hoppin==2 and ">" in connections) and connected and not blocked:
                            try:
                                maps = self.map.set(realX,realY,outtrack)
                                value = State_Pathfinder.toValue((realX,realY))
                                child = State_Pathfinder(maps,self,value)
                                self.children.append(child)
                            except ValueError as e:
                                print "Bad kid"
                                print e

# The solution function. Takes a map string
# and returns a map string.
def f(mapX):
    a = AStar_Solver(State_Pathfinder(mapX,0))
    a.solve()
    print a.path[-1]

if __name__ == "__main__":

    map1 = """###########
#    M    #
#   ^     #
>  ^^  M  #
#    ^    #
#~~~~~~~~~#
# M       #
#     ^^  #
#        M#
###########"""


    map2 = """#################
#               #
#   M         M #
#       ^       #
#        ^ M    #
#~~~~~~~^       #
#               #
#   ^           #
#   M^          #
#    ^          #
> ^^^          M#
#               #
#        M      #
#################"""

    map3 = """###############
# M   ~       #
#     ~       #
>     ~    M  #
#     ~       #
#     ~       #
#     ~       #
###############"""

    f(map3)
    f(map2)
    f(map1)

地图类

此类存储和处理地图。该isConnected方法可能是最重要的部分。它进行测试以查看是否连接了2条轨道。

from itertools import permutations,combinations

# A map class designed to hold string map
# the specification is found here:
# http://codegolf.stackexchange.com/questions/104965/ruby-on-rails-or-trackety-track
class Map(object):

    # Is 'track' part of the railroad?
    @staticmethod
    def isTrack(track):
        return track in ">|\\/-MX"

    # Can I not build on this terrian?
    @staticmethod
    def isBlocking(terrian):
        return terrian in "^#" or (Map.isTrack(terrian) and not terrian=="M")

    # Are these 3 consecuative tracks connected in a legal fashion?
    @staticmethod
    def isConnected(inTerrian,relativeXin,relativeYin,centerTerrian,relativeXout,relativeYout,outTerrian):
        tin = inTerrian
        xin = relativeXin
        yin = relativeYin
        x = relativeXout
        y = relativeYout
        tout = outTerrian
        center = centerTerrian

        if not Map.isTrack(center) or not Map.isTrack(tout):
            return False

        if tout in "MX" and center in "MX" and tout!=center:
            return True



        if center == ">":
            return x>0 and (\
                tout == "/" and y == -1 or \
                tout == "-" and y == 0 or \
                tout == "\\" and y == 1 \
                )

        if center == "M":
            return tout == "\\" and abs(x+y) == 2 or \
                tout == "/" and x+y == 0 or \
                tout == "|" and x == 0 or \
                tout == "-" and y == 0

        if center == "X":
            if xin!=0!=yin and abs(xin-x)+abs(yin-y) == 1:
                return False
            return tout == "\\" and abs(x+y) == 2 or \
                tout == "/" and x+y == 0 or \
                tout == "|" and x == 0 or \
                tout == "-" and y == 0

        if tout!="" and tout in "MX>" and tin!="" and tin in "MX>":
            return Map.isConnected("",0,0,tin,-xin,-yin,center) and Map.isConnected("",0,0,tout,-x,-y,center)
        elif tout!="" and tout in "MX>" and tin!="":
            return Map.isConnected("",0,0,center,xin,yin,tin) and Map.isConnected("",0,0,tout,-x,-y,center)
        elif tout!="" and tout in "MX>" and tin=="":
            return Map.isConnected("",0,0,tout,-x,-y,center)
        elif tin!="" and tin in "MX>":
            return Map.isConnected("",0,0,tin,-xin,-yin,center) and Map.isConnected("",0,0,center,x,y,tout)

        allowed = [ \
            ["-",-1,0,"-",1,0,"-"], \
            ["/",-1,1,"-",1,0,"-"], \
            ["\\",-1,-1,"-",1,0,"-"], \
            ["-",-1,0,"-",1,1,"\\"], \
            ["-",-1,0,"-",1,-1,"/"], \
            ["\\",-1,-1,"-",1,-1,"/"], \
            ["/",-1,1,"-",1,1,"\\"], \

            ["/",-1,1,"/",1,-1,"/"], \
            ["/",-1,1,"/",1,-1,"-"], \
            ["/",-1,1,"/",1,-1,"|"], \
            ["|",-1,1,"/",1,-1,"/"], \
            ["-",-1,1,"/",1,-1,"/"], \
            ["|",-1,1,"/",1,-1,"-"], \
            ["-",-1,1,"/",1,-1,"|"], \

            ["\\",-1,-1,"\\",1,1,"\\"], \
            ["\\",-1,-1,"\\",1,1,"-"], \
            ["\\",-1,-1,"\\",1,1,"|"], \
            ["|",-1,-1,"\\",1,1,"\\"], \
            ["-",-1,-1,"\\",1,1,"\\"], \
            ["|",-1,-1,"\\",1,1,"-"], \
            ["-",-1,-1,"\\",1,1,"|"], \

            ["|",0,-1,"|",0,1,"|"], \
            ["\\",-1,-1,"|",0,1,"|"], \
            ["/",1,-1,"|",0,1,"|"], \
            ["|",0,-1,"|",-1,1,"/"], \
            ["|",0,-1,"|",1,1,"\\"], \
            ["/",1,-1,"|",1,1,"\\"], \
            ["\\",-1,-1,"|",-1,1,"/"] \
        ]

        passing = False
        forward = [tin,xin,yin,center,x,y,tout]
        start = [0,3][tin==""]

        for allow in allowed:
            maybeF = True
            maybeB = True
            backallowed = [allow[6],allow[4],allow[5],allow[3],allow[1],allow[2],allow[0]]
            for i in range(start,len(allow)):
                if allow[i]!=forward[i] and str(forward[i])not in"*":
                    maybeF = False
                if backallowed[i]!=forward[i] and str(forward[i])not in"*":
                    maybeB = False
            if maybeF or maybeB:
                passing = True
        return passing

    def __init__(self,mapString):
        self.indexableMap = [list(x) for x in mapString.split("\n")]

    def __str__(self):
         return "\n".join(["".join(x) for x in self.indexableMap])

    # Get the string representation of this map
    def getDisplay(self):
        return self.__str__()

    # Get map width
    def getWidth(self):
        return len(self.indexableMap[0])

    # Get map height
    def getHeight(self):
        return len(self.indexableMap)

    # Get unvisited destinations
    def getDestinations(self):
        destinations = []
        for y in xrange(1,self.getHeight()-1):
            for x in xrange(1,self.getWidth()-1):
                sigma = 2
                if self.get(x,y)=="M":
                    sigma = len(self.getConnections(x,y,"M"))
                    if sigma==0:
                        destinations.append((x,y))
        return destinations

    # Get the x,y of the goal (endpoint)
    def getGoal(self):
        for y in xrange(self.getHeight()):
            for x in xrange(self.getWidth()):
                if self.get(x,y)==">":
                    return (x,y)

    # Get the x,y of the current location
    def getLocation(self):
        location = None
        for y in xrange(0,self.getHeight()-1):
            for x in xrange(0,self.getWidth()-1):
                track = self.get(x,y)
                sigma = len(self.getConnections(x,y,track))
                if track == ">":
                    if sigma==0:
                        location = (x,y)
                    sigma = 0
                if sigma == 1:
                    return (x,y)
        if location != None:
            return location
        raise ValueError('No location found in map\n'+self.getDisplay())

    # Get the terrian at x,y
    def get(self,x,y):
        return self.indexableMap[y][x]

    # Set the terrain at x,y
    # (non-destructive)
    def set(self,x,y,value):
        newMap = [[i for i in row] for row in self.indexableMap]
        newMap[y][x] = value
        return "\n".join(["".join(x) for x in newMap])

    # Get the track connectioning to a piece of track at x,y
    def getConnections(self,x,y,track):
        connections = []
        tracks = []
        for a,b in set(permutations([-1,-1,0,1,1],2)):
            outtrack = self.get(x+a,y+b)
            if Map.isTrack(outtrack) and Map.isConnected("",0,0,track,a,b,outtrack):
                tracks+=[[outtrack,a,b]]
        if len(tracks)==1:return [tracks[0][0]]
        if len(tracks)==0:return []

        for inner,outer in permutations(tracks,2):
            intrack,relXin,relYin = inner
            other,relX,relY = outer
            ex = x + relX
            ey = y + relY
            if Map.isConnected(intrack,relXin,relYin,track,relX,relY,other):
                if other == "M":
                    if len(self.getConnections(ex,ey,other))>=1:
                        connections.append(other)
                else:
                    connections.append(other)
        return connections

    # Is could a piece of track at x,y build in
    # the direct of relX,relY?
    def isBlocked(self,x,y,relX,relY):
        if relX==0 or relY==0:
            return False
        side1 = self.get(x+relX,y)
        side2 = self.get(x,y+relY)
        return (Map.isTrack(side1) or side1=="M")  and (Map.isTrack(side2) or side2=="M")

更新

  • -560 [17-03-31]一堆基本的正则表达式高尔夫
  • +982 [17-03-31]修复了非法铺设轨道的问题。谢谢@ fəˈnɛtɪk
  • -99 [17-03-31]已使用;s

更改一些用于打高尔夫球的变量名称;)
马修·罗

6
您应该能够通过结合使用空格和制表符进行缩进来进一步打高尔夫球
John Dvorak

2
开头的两行elif e!=""and e in"MX>"可以合并为具有三进制的一行if else。另外,您def的某些可能是lambda。像def A(s):return str(s)可以是A=lambda s:str(s),或者如果从更改__str____repr__,则可以使用 A=lambda s:`s`,这时甚至不值得拥有A它自己的功能,因为它需要括号来调用。只需使用反引号即可。
mbomb007 '17

该代码在构建网桥时会尝试非法移动。我不能肯定地说这是一个问题,因为它以有效路径结束了测试用例。
fəˈnɛtɪk

什么!我不知道这是做的。我试图做到这一点,但从未完成过,但是做得很好!
Christopher
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.