算法以在x回合内到达的速度。

huangapple go评论66阅读模式
英文:

algorithm to calculate speeds to move in order to arrive in x turns

问题

给定一个 distance(距离)和 turns(回合数),计算在每个速度(1、2、4和8)上需要多少回合才能完成最后一次加速以完成距离。

你从速度1开始,每个回合可以加速到下一个速度或什么都不做(1 -> 2,2 -> 4,4 -> 8),一旦加速,就不能减速。

每个回合你移动 speed 步(distance -= speed)。

此外,只有在最后一个回合才能超过 distance 步。

例如:distance = 25,turns = 10 -> 速度1:1回合,速度2:5回合,速度4:4回合,总距离为1 * 1 + 2 * 5 + 4 * 4 = 27步,但我们在最后一回合达到了25步,这正是我们需要的。

我需要帮助编写一个计算这个问题的函数。

def calc_speeds(distance: int, arrive_in_x_turns: int) -> dict[int, int]:

到目前为止,我已经使用了这个公式 turns_till_arrival = ((turns_till_arrival - (speed // 2)) // speed) + (speed // 2) + 1,在一个循环中,针对每个速度,如果 turns_till_arrival 等于 turns,我将加速直到达到 speed 而不会在其他速度上花费额外的回合(只需要1个必要的回合,因为我每回合只能加速一次),但是有很多情况下它不起作用,因为为了让它起作用,我必须在其他速度上花费超过1回合的时间,但我无法想出一种计算方法。

英文:

given a distance, turns calculate the number of turns to be on each speed - 1 2 4, and 8. to complete the distance on the last turn.

you start on speed 1, and in each turn you can accelerate to the next speed or do nothing (1 -> 2, 2 -> 4, 4 -> 8), once you accelerate you can't slow back down.

each turn you are moving speed steps (distance -= speed).

also, it's ok to go more than distance steps but only if it happens on the last turn.

for example: distance = 25, turns = 10 -> speed 1: 1 turn, speed 2: 5 turns, speed 4: 4 turns, the total distance is 1 * 1 + 2 * 5 + 4 * 4 = 27 steps, but we got to 25 steps on the last turn which is what we need.

I need help writing a function that will calculate that.

def calc_speeds(distance: int, arrive_in_x_turns: int) -> dict[int, int]:

so far i've used this turns_till_arrival = ((turns_till_arrival - (speed // 2)) // speed) + (speed // 2) + 1 formula, in a for loop, for each speed and if turns_till_arrival is equal to turns I will accelerate until I get to speed without spending extra turns in other speeds (only the 1 necessary turn, because I can only accelerate once per turn) but then there are a lot of times that it doesn't work because in order for it to work I must spend more than 1 turn at other speeds but I can't figure out a way to calculate that.

答案1

得分: 1

这是一个相当详尽的方法,但它确实提供了如何在指定数量的步骤内覆盖您的距离的正确答案。

对于我的方法,我首先创建了一个以{1: 距离, 2: 0, 4: 0, 8: 0}形式的输出字典,其中,对于每个键值对,键表示您的速度,值表示在该速度下花费的总转数。上述字典代表了以最大转数覆盖您的距离的方式,因为每个转数您都只是以速度=1奔跑。

这里的重要认识是,如果您从output[1]减去两个转数并增加一个转数到output[2],您覆盖的距离与以前相同,但您已经失去了一个转数。因此,您可以创建一个循环,当您输出的转数等于arrive_in_x_turns时停止,并且在每次迭代中,通过执行我上面描述的子过程来失去一个转数。这也适用于其他速度(即从output[2]减去两个转数并添加一个转数到output[4]会保持您希望旅行的距离,同时失去一个转数)。

以下是我的实现。当运行您的示例calc_speeds(distance=25, arrive_in_x_turns=10)时,我的输出是{1: 1, 2: 6, 4: 3, 8: 0}。转数是正确的(1 + 6 + 3 = 10),距离覆盖也正确(1*1 + 2*6 + 4*3 + 8*0 = 1 + 12 + 12 + 0 = 25)。

def calc_speeds(distance: int, arrive_in_x_turns: int) -> dict[int, int]:
    output = {1: distance, 2: 0, 4: 0, 8: 0}

    # 循环直到总转数等于请求的转数
    while (sum(output.values()) > arrive_in_x_turns):
        # 从'1'减去两个转数并添加一个转数到'2',直到不再可能
        # 这种方法确保在每次迭代中,转数减少一个,而旅行距离保持不变
        if output[1] // 2 > 0:
            output[1] -= 2
            output[2] += 1
        # 对上述的其他速度执行类似的方法
        elif output[2] // 2 > 0:
            output[2] -= 2
            output[4] += 1
        elif output[4] // 2 > 0:
            output[4] -= 2
            output[8] += 1
    
    return output

再次强调,这是一个详尽的解决方案,对于更复杂的示例,运行时间会很长,但希望这将帮助您开始寻找更优化的解决方案!

编辑:

这个答案可以进行优化!不必从当前速度中减去两个转数并添加一个转数到下一个速度,我们可以找到当前速度的转数的一半与剩余需要去掉的转数之间的最小值。以下是一个更新版本。

def calc_speeds(distance: int, arrive_in_x_turns: int) -> dict[int, int]:
    output = {1: distance, 2: 0, 4: 0, 8: 0}

    # 循环直到总转数等于请求的转数
    while sum(output.values()) > arrive_in_x_turns:
        if output[1] // 2 > 0:
            # 计算要从当前速度减去的转数,作为当前速度下转数的一半与剩余的转数之间的最小值
            turns_to_subtract = min(output[1] // 2, sum(output.values()) - arrive_in_x_turns)
            # 使用与先前版本的算法类似的逻辑
            output[1] -= turns_to_subtract * 2
            output[2] += turns_to_subtract
        elif output[2] // 2 > 0:
            turns_to_subtract = min(output[2] // 2, sum(output.values()) - arrive_in_x_turns)
            output[2] -= turns_to_subtract * 2
            output[4] += turns_to_subtract
        elif output[4] // 2 > 0:
            turns_to_subtract = min(output[4] // 2, sum(output.values()) - arrive_in_x_turns)
            output[4] -= turns_to_subtract * 2
            output[8] += turns_to_subtract
    
    return output
英文:

This is a fairly exhaustive approach, but it does provide the correct answer to the problem above about how to cover your distance in a specified number of steps.

For my method, I first created the output dictionary in the form of {1: distance, 2: 0, 4: 0, 8: 0}, where, for each key-value pair, the key represents your speed and the value represents the total number of turns spent at that speed. This dictionary above represents the way to cover your distance in the maximum number of turns possible, since each turn you are just running at speed=1.

The important realization here is that if you subtract two turns from output[1] and add a turn to output[2], you are covering the same distance as before, but you have lost a turn. Therefore, you can make a loop that stops when the number of turns in your output equals arrive_in_x_turns, and during each iteration, you lose a turn by doing the subprocess I have described above. This also works for the other speeds (i.e. subtracting two turns from output[2] and adding a turn into output[4] maintains the distance you want to travel while losing a turn).

Here is my implementation below. When running your example of calc_speeds(distance=25, arrive_in_x_turns=10), my output is {1: 1, 2: 6, 4: 3, 8: 0}. The number of turns are correct (1 + 6 + 3 = 10), as is the distance covered (1*1 + 2*6 + 4*3 + 8*0 = 1 + 12 + 12 + 0 = 25).

def calc_speeds(distance: int, arrive_in_x_turns: int) -> dict[int, int]:
    output = {1: distance, 2: 0, 4: 0, 8: 0}

    # Loop until the total number of turns is equal to the number of turns requested
    while (sum(output.values()) > arrive_in_x_turns):
        # Subtract two turns off of '1' and add a turn to '2' until not possible
        # This method ensures that during each iteration, number of turns decreases
        # by one while the distance traveled remains the same
        if output[1] // 2 > 0:
            output[1] -= 2
            output[2] += 1
        # Do a similar method for the ones above
        elif output[2] // 2 > 0:
            output[2] -= 2
            output[4] += 1
        elif output[4] // 2 > 0:
            output[4] -= 2
            output[8] += 1
    
    return output

Again, this is an exhaustive solution that will have a long runtime with harder examples, but hopefully this will help get you started on finding a more optimal way to solve it!

EDIT:

This answer above can be optimized! Instead of subtracting two turns from a current speed and adding one turn to the next, we can instead find the minimum between half the number of turns of the current speed and the remaining number of turns that need to be gotten rid of. Here's a newer version.

def calc_speeds(distance: int, arrive_in_x_turns: int) -> dict[int, int]:
    output = {1: distance, 2: 0, 4: 0, 8: 0}

    # Loop until the total number of turns is equal to the number of turns requested
    while sum(output.values()) > arrive_in_x_turns:
        if output[1] // 2 > 0:
            # Calculate turns to subtract from current speed as the minimum between half the 
            # current turns under this speed and the number of turns remaining
            turns_to_subtract = min(output[1] // 2, sum(output.values()) - arrive_in_x_turns)
            # Use similar logic to the previous version of this algorithm
            output[1] -= turns_to_subtract * 2
            output[2] += turns_to_subtract
        elif output[2] // 2 > 0:
            turns_to_subtract = min(output[2] // 2, sum(output.values()) - arrive_in_x_turns)
            output[2] -= turns_to_subtract * 2
            output[4] += turns_to_subtract
        elif output[4] // 2 > 0:
            turns_to_subtract = min(output[4] // 2, sum(output.values()) - arrive_in_x_turns)
            output[4] -= turns_to_subtract * 2
            output[8] += turns_to_subtract
    
    return output

huangapple
  • 本文由 发表于 2023年6月1日 22:31:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76382996.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定