zltzlt 发表于 2020-4-16 20:48:13

March2615 发表于 2020-4-16 12:57
不知不觉一下午过去了

17 ms

zltzlt 发表于 2020-4-16 20:49:10

TJBEST 发表于 2020-4-16 14:58
来看看我的史诗巨作,历时1个小时20分钟

输入以下数据超时:

zltzlt 发表于 2020-4-16 20:50:10

kinkon 发表于 2020-4-16 15:21
优化一下

15 ms

zltzlt 发表于 2020-4-16 20:51:25

whosyourdaddy 发表于 2020-4-16 20:11
def func377(arr):
    def distance( p,q):
      return (p-q) * (p-q) + (p-q) ...

解答错误

输入:[, , , , , , , ]
输出:[, , , , , ]
预期结果:[, , , , , ]

ouyunfu 发表于 2020-4-16 21:35:12

import math
def f377(points):
    n = len(points)
    if n == 0:
      return 0
    if n <= 3:
      return points
   
    def get_bottom_point(points):
      min_index = 0
      n = len(points)
      for i in range(0, n):
            if points < points or (points == points and points < points):
                min_index = i
      return min_index

    def f2(points, center_point):
      n = len(points)
      cos_value = []
      rank = []
      norm_list = []
      for i in range(0, n):
            point_ = points
            point = -center_point, point_-center_point]
            rank.append(i)
            norm_value = math.sqrt(point*point + point*point)
            norm_list.append(norm_value)
            if norm_value == 0:
                cos_value.append(1)
            else:
                cos_value.append(point / norm_value)
      for i in range(0, n-1):
            index = i + 1
            while index > 0:
                if cos_value > cos_value or (cos_value == cos_value and norm_list > norm_list):
                  temp = cos_value
                  temp_rank = rank
                  temp_norm = norm_list
                  cos_value = cos_value
                  rank = rank
                  norm_list = norm_list
                  cos_value = temp
                  rank = temp_rank
                  norm_list = temp_norm
                  index = index-1
                else:
                  break
      sorted_points = []
      for i in rank:
            sorted_points.append(points)
   
      return sorted_points
   
    def vector_angle(vector):
      norm_ = math.sqrt(vector*vector + vector*vector)
      if norm_ == 0:
            return 0
   
      angle = math.acos(vector/norm_)
      if vector >= 0:
            return angle
      else:
            return 2*math.pi - angle
   
    def coss_multi(v1, v2):
      return v1*v2 - v1*v2

    bottom_index = get_bottom_point(points)
    bottom_point = points.pop(bottom_index)
    sorted_points = f2(points, bottom_point)
    m = len(sorted_points)
    if m <2 :
      return points
    stack = []
    stack.append(bottom_point)
    stack.append(sorted_points)
    stack.append(sorted_points)
    for i in range(2, m):
      length = len(stack)
      top = stack
      next_top = stack
      v1 = -next_top, sorted_points-next_top]
      v2 = -next_top, top-next_top]
      while coss_multi(v1, v2) > 0:
            stack.pop()
            length = len(stack)
            top = stack
            next_top = stack
            v1 = - next_top, sorted_points - next_top]
            v2 = - next_top, top - next_top]

      stack.append(sorted_points)
    return stack

print(f377([, , ]))
print(f377([, , , , , ]))

zltzlt 发表于 2020-4-16 22:43:22

总想起个好名字 发表于 2020-4-16 22:23


爱叫什么叫什么 发表于 2020-4-17 11:09:10

数学不好的人飘过...高等数学没有学过...怎么办

TJBEST 发表于 2020-4-17 11:16:20

本帖最后由 TJBEST 于 2020-4-17 17:18 编辑

楼主帮忙测测吧 @zltzlt
def fun377(points):
    if len(points) < 4:
      return points
    dealWith = sorted(points)
    Left = dealWith
    Right = dealWith[-1]
    del dealWith
    result =
   
    previous = Left
    while True:
      if previous == Left:
            comList = > previous) or (i > previous)]
      elif previous == Right:
            comList = == previous) and (i < previous)]
      else:
            comList = > previous]
      comList.sort()
      if comList == Left:
            previous = comList
            result.append(previous)
            dealWith.remove(previous)
      elif previous == Right:
            previous = comList[-1]
            result.append(previous)
            dealWith.remove(previous)
      else:
            comList.sort(key = lambda ex:(((ex-previous)/(ex-previous)),-ex))
            previous = comList.pop()
            result.append(previous)
            dealWith.remove(previous)
      if previous == Right:
            break
    dealWith.append(Left)
    while True:
      if previous == Left:
            comList = ==previous) and (i > previous)]
      elif previous == Right:
            comList = < previous) or (i < previous)]
      else:
            comList = < previous]
      comList.sort()
      if comList[-1] == Right:
            previous = comList.pop()
            result.append(previous)
            dealWith.remove(previous)
      elif previous == Left:
            previous = comList
            result.append(previous)
            dealWith.remove(previous)
      else:
            comList.sort(key = lambda ex:(((ex-previous)/(ex-previous)),ex))
            previous = comList.pop()
            result.append(previous)
            dealWith.remove(previous)
      if previous == Left:
            result.remove(Left)
            break
    return result

kinkon 发表于 2020-4-17 11:33:45

本帖最后由 kinkon 于 2020-4-17 11:37 编辑

自己想的一个测试用例:[, , , , , , , ,]
输出:[, , , , ]

zltzlt 发表于 2020-4-17 13:24:46

ouyunfu 发表于 2020-4-16 21:35


解答错误

输入:[, , , , , , , , , , , , , , , , , ]
输出:[, , , , , , , , , , , , , , , ]
预期结果:[, , , , , , , , , , , , , , , ]

TJBEST 发表于 2020-4-17 17:16:56

@zltzlt 楼主 新代码见28层

howzyao 发表于 2020-4-17 18:13:41

待我上机我来画的试试

zltzlt 发表于 2020-4-17 18:44:32

TJBEST 发表于 2020-4-17 11:16
楼主帮忙测测吧 @zltzlt

56 ms

阴阳神万物主 发表于 2020-4-18 01:56:48

本帖最后由 阴阳神万物主 于 2020-4-18 05:36 编辑

难度评级:普通
要素分析:数论
随机输入生成器,送给有需要的人:如果觉得好用,麻烦评个分呗
from random import randint as r
def gent(x=,y=,m=8,n=5,f=False):
    '''
    参数说明:
      x:'横轴取值闭区间'默认为
      y:'纵轴取值闭区间'默认为
      m:'最多允许多少棵树'默认为8
      n:'生成数量'默认生成5个测试数据
      f:'是否固定树的颗数'默认为随机颗树
    '''
    x1,x2 = x
    y1,y2 = y
    size = min((x2-x1+1)*(y2-y1+1),m)
    for i in range(n):
      lst = []
      for j in range(size if f else r(1,size)):
            while 1:
                pos =
                if pos not in lst:
                  lst.append(pos)
                  break
      yield lst



解题代码1:
def solve(trees:'list og points by list')->list:
    class Func:
      '''
      y = kx + b
      k = (y1-y2)/(x1-x2)
      b = y - kx
      '''
      def __init__(self,p1,p2):
            x1,y1 = p1
            x2,y2 = p2
            self.k = (y1-y2)/(x1-x2) if x1!=x2 else None
            self.b = y1 - self.k*x1 if self.k!=None else x1
      def cmp(self,pos):
            x,y = pos
            if self.k==None:return 0 if x==self.b else 1 if x > self.b else -1
            ny = self.k*x + self.b
            return 0 if y==ny else 1 if y > ny else -1
    res = []
    l = len(trees)
    if l <= 3:return trees
    for a in range(l-1):
      for b in range(a+1,l):
            f =Func(trees,trees)
            c =
            if not(1 in c and -1 in c):
                while 0 in c:
                  n = c.index(0)
                  if trees not in res:res.append(trees)
                  c += 1
    return res

if __name__ == '__main__':
    print('示例1 输出:',solve([, , , , , ]))
    print('示例2 输出:',solve([, , ]))

思路解说:
整体就是一个简单的线性规划问题,所有点两两相连,若所有点都在线的同一侧或者就在线上,那么这条线就是边界。
当然,我上面这个属于是暴力规划,还有更加巧妙的,就是下面那个。

解题代码2:
class Func:
    '''
    y = kx + b
    k = (y1-y2)/(x1-x2)
    b = y - kx
    '''
    def __init__(self,p1,p2):
      x1,y1 = p1
      x2,y2 = p2
      self.k = (y1-y2)/(x1-x2) if x1!=x2 else None
      self.b = y1 - self.k*x1 if self.k!=None else x1
    def cmp(self,pos):
      x,y = pos
      if self.k==None:return 0 if x==self.b else 1 if x > self.b else -1
      ny = round(self.k*x + self.b,1)
      return 0 if y==ny else 1 if y > ny else -1
   
def solve(trees:'list og points by list')->list:
    res = []
    l = len(trees)
    if l <= 3:return trees
    trees.sort()
    a,b = 0,0
    plan = *l#标记非端边界点
    flg = 1
    while flg:
      b = (b+1)%l
      if plan:continue
      if b == a:a = (a+1)%l;b=a
      f =Func(trees,trees)#解析直线函数
      c = #检查所有点与直线的关系
      if not(1 in c and -1 in c):#所有点均在直线的同一侧,或者在直线上
            online = []
            while 0 in c:
                n = c.index(0)
                online.append(trees)
                if trees not in res:res.append(trees)#将边界点加入输出列表
                elif not plan:flg = 0
                c += 1
                if n!=a:plan = 1
            online.sort()
            ia = online.index(trees)
            ib = online.index(trees)
            a = trees.index(online[-1 if ib>ia else 0])
            b = a#从线的一端直接到另一端,跳过中间的已被标记的点
    return res
      
if __name__ == '__main__':
    print('示例1 输出:',solve_1([, , , , , ]))
    print('示例2 输出:',solve_1([, , ]))
   
我自己测试的用时是,在51*51的区域内,最多允许60颗树存在,100个随机测试用例
法一平均用时:36.3805ms
法二平均用时:6.2350ms
我自己测试用时的代码:
>>> import time
>>> def pt(b,x=5,y=5):      #在发现输出数据不同时,用平面图的方式呈现出数据,便于肉眼分辨
      plan = [*y for i in range(x)]
      for i,j in b:
                plan = 1
      for line in plan:
                print(line)

>>> if 1:
      t1,t2 = [],[]
      for each in gent(,,m=60,n=100):
                a = time.perf_counter()
                s1 = solve_1(each)
                b = time.perf_counter()
                t1.append((b-a)*1000)
                a = time.perf_counter()
                s2 = solve_2(each)
                b = time.perf_counter()
                t2.append((b-a)*1000)
                for each in s1:          #这个二层循环是检查两种方法的结果是否一致的,如不需要,可直接删去
                        if each not in s2:
                              print('input',len(each))
                              pt(each,51,51)
                              print('s1',(s1))
                              pt(s1,51,51)
                              print('s2',(s2))
                              pt(s2,51,51)
                              break
      print('法一平均用时:%0.4fms\n法二平均用时:%0.4fms\n总共用时%0.4fms'%(sum(t1)/len(t1),sum(t2)/len(t2),sum(t1+t2)))

archlzy 发表于 2020-4-18 11:45:30

import math

def fun377(input_list):
    if len (input_list) <4:
      return input_list
    else:
      temp_list = input_list
      
      def test_inner():
            """"
            calc_p 检测点 other_p 其他点的列表
            返回值 : True 是内部点, False 不是内部点
            检测函数 检测点 所有边都不能夹角 找不到大于 pi的
            那么这个点就是内部点,否则就是 位于边界上的点
            """
            vector_list = [(i-calc_p, j-calc_p) for i,j in other_p]
            deg_list=[]
            for x,y in vector_list:
                r = (x**2 +y**2)**0.5
                deg = math.acos(x/r)
                if y<0:
                  deg = -deg + math.pi *2
                deg_list.append(deg)
            deg_list.sort()
            for i in range(len(deg_list)):
                if i == len(deg_list) -1:
                  if math.pi *2 - deg_list[-1] + deg_list>= math.pi:
                        break
                elif deg_list - deg_list >= math.pi:
                  break
            else:
                return True
            return False
            
      num = 0 # 从0位置开始 记住上次跳出的 for 循环计数 i 进入下一个for 其实从 i 开始
      while num < len(temp_list):
            for i in range(num, len(temp_list)):   
                calc_p = temp_list
                other_p = temp_list[:i] + temp_list
                if test_inner():
                  temp_list.remove(calc_p)
                  num = i
                  break
            else: # 如果for循环 走完了没有被打断说明 现在for里面的都是外部点
                return temp_list
      return temp_list

风魔孤行者 发表于 2020-4-18 16:59:55

def f(list1):
    def x(list1):
      return list1
    def y(list1):
      return list1
    list2 = []
    list1 = sorted(list1,key=x)
    xmin = list1
    xmin_list = []
    xmax = list1[-1]
    xmax_list = []
    for each in list1:
      if each == xmin:
            list2.append(each)
            xmin_list.append(each)
      elif each == xmax:
            list2.append(each)
            xmax_list.append(each)
   
    list1 = sorted(list1,key=y)
    ymin = list1
    ymin_list = []
    ymax = list1[-1]
    ymax_list = []
    for each in list1:
      if each == ymin:
            list2.append(each)
            ymin_list.append(each)
      elif each == ymax:
            list2.append(each)
            ymax_list.append(each)

    xmin_list.sort()
    xmax_list.sort()
    ymin_list.sort()
    ymax_list.sort()

    def f1(p1,p2,p3):
      if abs((p2-p1)/(p2-p1))<abs((p3-p1)/(p3-p1)):
            return 2
      elif abs((p2-p1)/(p2-p1))==abs((p3-p1)/(p3-p1)):
            return 1
      else:
            return 0
      
    leftup,leftdown,rightup,rightdown = list1[:],list1[:],list1[:],list1[:]
    p1,p2,p3,p4,p5,p6,p7,p8 = ],,ymax],,ymax],],],,ymin],,ymin],]
    h1,h2,h3,h4 = [],[],[],[]
    while leftup != []:
      for each in leftup.copy():
            if each>=p2 or each<=p1:
                leftup.remove(each)
            else:
                if f1(p1,p2,each)==2:
                  h1 = []
                  h1.append(each)
                  p2 = each
                elif f1(p1,p2,each)==1:
                  h1.append(each)
      if h1 != []:
            list2 += h1
            h1 = sorted(h1,key=y)
            p1 = h1[-1]
            p2 = ,ymax]
            for m in h1:
                leftup.remove(m)
      else:
            break
    while rightup != []:
      for each in rightup.copy():
            if each<=p3 or each<=p4:
                rightup.remove(each)
            else:
                if f1(p4,p3,each)==2:
                  h2 = []
                  h2.append(each)
                  p3 = each
                elif f1(p4,p3,each)==1:
                  h2.append(each)
      if h2 != []:
            list2 += h2
            h2 = sorted(h2,key=y)
            p4 = h2[-1]
            p3 = ,ymax]
            for m in h2:
                rightup.remove(m)
      else:
            break
    while leftdown != []:
      for each in leftdown.copy():
            if each>=p7 or each>=p8:
                leftdown.remove(each)
            else:
                if f1(p8,p7,each)==2:
                  h4 = []
                  h4.append(each)
                  p7 = each
                elif f1(p8,p7,each)==1:
                  h4.append(each)
      if h4 != []:
            list2 += h4
            h4 = sorted(h4,key=x)
            p8 = h4[-1]
            p7 = ,ymin]
            for m in h4:
                leftdown.remove(m)
      else:
            break
    while rightdown != []:
      for each in rightdown.copy():
            if each<=p6 or each>=p5:
                rightdown.remove(each)
            else:
                if f1(p5,p6,each)==2:
                  h3 = []
                  h3.append(each)
                  p6 = each
                elif f1(p5,p6,each)==1:
                  h3.append(each)
      if h3 != []:
            list2 += h3
            h3 = sorted(h3,key=x)
            p5 = h3
            p6 = ,ymin]
            for m in h3:
                rightdown.remove(m)
      else:
            break
    return list2{:10_266:}{:10_266:}{:10_266:}

zltzlt 发表于 2020-4-18 17:28:11

阴阳神万物主 发表于 2020-4-18 01:56
难度评级:普通
要素分析:数论
随机输入生成器,送给有需要的人:如果觉得好用,麻烦评个分呗


两段代码输入以下数据都会超时:



zltzlt 发表于 2020-4-18 17:30:17

archlzy 发表于 2020-4-18 11:45


输入以下数据超时:

zltzlt 发表于 2020-4-18 17:30:59

风魔孤行者 发表于 2020-4-18 16:59


输入 [, , ] 出错
页: 1 [2]
查看完整版本: Python:每日一题 377