<
ARTS 第一周
>
上一篇

使用 Consul 作为 Python 微服务的配置中心
下一篇

ARTS 第二周
Toc
ARTS Week-1

Algorithm

1014. 在 D 天内送达包裹的能力

题目描述:

传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。

传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。

示例:

输入:weights = [1,2,3,4,5,6,7,8,9,10], D = 5
输出:15
解释:
船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示:
第 1 天:1, 2, 3, 4, 5
第 2 天:6, 7
第 3 天:8
第 4 天:9
第 5 天:10

请注意,货物必须按照给定的顺序装运,因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。

解题思路:

这道题主要利用二分法解题,用二分法则需要起始的最大最小值,即左区间和右区间。

我们不妨设定区间为,[max(weights), sum(weights)] :

然后取中间值尝试运送货物,中间值记为 mid,并用 day 计算使用 mid 作为船舶的最低载重时需要运送多少天。

day 大于 Dmid 值小了,左区间变为 mid + 1

day 小于等于 Dmid 值大了,右区间变为 mid - 1

直到左区间无法在变大,右区间无法在变小,即限制条件 [left, right]left ≤ right

代码:

class Solution:
    def shipWithinDays(self, weights: List[int], D: int) -> int:
        left, right = max(weights), sum(weights)
        
        while left <= right:

            day_weight = 0
            day = 1
            mid = (left + right) // 2

            for w in weights:
                if day_weight + w <= mid:
                    day_weight += w
                else:
                    day_weight = w
                    day += 1
            
            if day > D:
                left = mid + 1
            else:
                right = mid - 1
        
        return left

Github 仓库地址

Review

Fallacies of Distributed Computing Explained.pdf

《分布式系统的谬论解释》

这篇英文文章主要介绍并解释了 8 条分布式系统的谬论,它们分别是:

  1. 网络是可靠的
  2. 网络没有延迟
  3. 网络带宽是无限大的
  4. 网络是安全的
  5. 网络拓扑是不会变的
  6. 只有一个超级管理员
  7. 网络传输没有消耗
  8. 网络是同构的

由于存在非常多的不可抗力会导致网络问题,如:交换机的故障、网络供应商服务提供故障,甚至有可能是某人把你的网线弄断了等等原因都可能导致网络不可用。

所以在设计分布式系统时,需要从硬件和软件两方面考虑

从基础设施方面,你需要考虑硬件和软件的冗余,并且权衡投入的资金和风险带来的损失。我们经常听到的风控就是与之相关的,若避免这方面的问题的投入非常大,还不如利用风控资金来补偿用户。

在软件方面,你要考虑无论你是发出消息还是发出请求,都有不可达的情况。当消息非常重要时,需要做到发送重试、响应到达、保证消息不重复和幂等性等等。

文章还提到了网络延迟问题比带宽问题更大,网络延迟往往也会影响数据的一致性。

除了这些还需要考虑网络的安全性,一些公司为安全问题赔偿了大量的资金,所以安全尤为重要。

文章指出,通常可以考虑多层安全的解决方案来保证安全性,从保证网络、基础服务和应用层次的安全来保证系统的安全。

我对这几点谬论的解释和相应的解决方案印象比较深刻,所以在这里简要说明了一下,其他几点也是在分布式系统设计时也是要考虑的,当然有兴趣的可以和我一样去阅读一下这篇文章。

Tip

利用 Pytest 中的 monkeypatch 来进行单元测试

由于 Python 是一门动态语言,他与强类型语言不同,任何变量的类型随时可能会变化,因此写出来的代码非常容易出 BUG,所以单元测试在 Python 开发中尤为重要。

但是一旦想开始写测试,就有一个问题。“我的代码该如何测试?”

这里有一份适合初学者的文档 《learning-pytest》,我觉得作者写的很好但是为什么 star 这么少呢,赶紧给个 🌟 吧。

其中我觉得最为精髓,pytest 最强大的地方就是 monkeypatch

举个例子,当我们要测试的类或函数,需要调用另一个类的方法,而另一个类的方法恰好有调用了其他服务的接口。这里我们就可以 Mock 我们需要调用的类或方法,比如说:

我们要调用一个第三方的天气服务:

class WeatherService:
	def get_weather(city_id, **kwargs, #... 非常多的参数,可能参数是字典并且带有格式):
			# requests....
			return # Somethings

class MyService:
	_weather_service_cls = monkeypatch
	def run(city_id, **kwargs):
		return self._weather_service_cls().get_weather(city_id, **kwargs)

我们需要写单元测试保证我们调用时的传入参数正确,这里就利用 monkeypatchMock 一个 WeatherService

import pytest
from . import MyService

class MockWeatherService:
	 get_weather_locals = None
	 def def get_weather(city_id, **kwargs):
			MockWeatherService.get_weather_locals = locals()

# 利用 monkeypatch 修改 MyService 的 _weather_service_cls
@pytest.fixture(autouse=True)
def mocker(monkeypatch):
    monkeypatch.setattr(MyService, '_weather_service_cls', MockWeatherService)

def test_run():
	  ms = MyService()
		city_id = 'xxxx'
    kwargs = {'xxx':'xxx', 'xxxx':'xxxx'}
    ms.run(city_id, **kwargs)
    assert MockWeatherService.get_weather_locals['city_id'] == city_id
		# assert kwargs ...

利用 pytest 的 monkeypatch 我们就可以专注与测试我们想测试的类,不用考虑其他依赖的类。

Share

左耳听风 《程序员如何利用技术变现 下》

在学习技术的过程中一定要多问自己两个问题:“一,这个技术解决了什么问题?为什么别的同类技术做不到?二,为什么是这样解决的?有没有更好的方式?“

Top
Foot