2024-08-10    2024-08-29     4477 字  9 分钟

Data Structure

Buffer

Traffic light

Description

https://www.codewars.com/kata/58649884a1659ed6cb000072/

You’re writing code to control your town’s traffic lights. You need a function to handle each change from green, to yellow, to red, and then to green again.

Complete the function that takes a string as an argument representing the current state of the light and returns a string representing the state the light should change to.

For example, when the input is green, output should be yellow.

def update_light(current):
    pass

Solutions


def update_light(current):
    lights_pairs = {"green": "yellow", "yellow": "red", "red": "green"}
    
    for key, value in lights_pairs.items():
        if current == key:
            return value

def update_light(current):
    return {"green": "yellow", "yellow": "red", "red": "green"}[current]


class Node:
    def __init__(self, state):
        self.state = state
        self.next = None

class TrafficLight:
    def __init__(self):
        # 创建链表节点
        self.green = Node("green")
        self.yellow = Node("yellow")
        self.red = Node("red")
        
        # 链接节点
        self.green.next = self.yellow
        self.yellow.next = self.red
        self.red.next = self.green
        
        # 初始化当前状态为 green
        self.current = self.green
    
    def change_light(self, current_state):
        # 遍历链表查找当前状态
        temp = self.green
        while temp:
            if temp.state == current_state:
                # 更新当前状态
                self.current = temp.next
                return self.current.state
            temp = temp.next
        return "Invalid State"

traffic_light = TrafficLight()
print(traffic_light.change_light("green"))   # 输出: "yellow"
print(traffic_light.change_light("yellow"))  # 输出: "red"
print(traffic_light.change_light("red"))     # 输出: "green"

Reverse or rotate?

Description

https://www.codewars.com/kata/56b5afb4ed1f6d5fb0000991/

The input is a string str of digits. Cut the string into chunks (a chunk here is a substring of the initial string) of size sz (ignore the last chunk if its size is less than sz).

If the sum of a chunk’s digits is divisible by 2, reverse that chunk; otherwise rotate it to the left by one position. Put together these modified chunks and return the result as a string.

If

  • sz is <= 0 or if str == "" return ""
  • sz is greater (>) than the length of str it is impossible to take a chunk of size sz hence return "".
Examples:
("123456987654", 6) --> "234561876549"
("123456987653", 6) --> "234561356789"
("66443875", 4) --> "44668753"
("66443875", 8) --> "64438756"
("664438769", 8) --> "67834466"
("123456779", 8) --> "23456771"
("", 8) --> ""
("123456779", 0) --> "" 
("563000655734469485", 4) --> "0365065073456944"
Example of a string rotated to the left by one position:
s = "123456" gives "234561".

Solution

def rev_rot(strng, sz):
    if sz <= 0 or not strng or sz > len(strng):
        return ""
    
    result = []
    for i in range(0, len(strng), sz):
        chunk = strng[i:i+sz]
        if len(chunk) < sz:
            continue
        
        digit_sum = sum(int(char) for char in chunk)
        if digit_sum % 2 == 0:
            result.append(chunk[::-1])
        else:
            result.append(chunk[1:] + chunk[0])
    
    return "".join(result)

Strings Mix

Description

https://www.codewars.com/kata/5629db57620258aa9d000014/

Given two strings s1 and s2, we want to visualize how different the two strings are. We will only take into account the lowercase letters (a to z). First let us count the frequency of each lowercase letters in s1 and s2.

s1 = "A aaaa bb c"

s2 = "& aaa bbb c d"

s1 has 4 'a', 2 'b', 1 'c'

s2 has 3 'a', 3 'b', 1 'c', 1 'd'

So the maximum for 'a' in s1 and s2 is 4 from s1; the maximum for 'b' is 3 from s2. In the following we will not consider letters when the maximum of their occurrences is less than or equal to 1.

We can resume the differences between s1 and s2 in the following string: "1:aaaa/2:bbb" where 1 in 1:aaaa stands for string s1 and aaaa because the maximum for a is 4. In the same manner 2:bbb stands for string s2 and bbb because the maximum for b is 3.

The task is to produce a string in which each lowercase letters of s1 or s2 appears as many times as its maximum if this maximum is strictly greater than 1; these letters will be prefixed by the number of the string where they appear with their maximum value and :. If the maximum is in s1 as well as in s2 the prefix is =:.

In the result, substrings (a substring is for example 2:nnnnn or 1:hhh; it contains the prefix) will be in decreasing order of their length and when they have the same length sorted in ascending lexicographic order (letters and digits - more precisely sorted by codepoint); the different groups will be separated by '/'. See examples and “Example Tests”.

Hopefully other examples can make this clearer.

s1 = "my&friend&Paul has heavy hats! &"
s2 = "my friend John has many many friends &"
mix(s1, s2) # --> "2:nnnnn/1:aaaa/1:hhh/2:mmm/2:yyy/2:dd/2:ff/2:ii/2:rr/=:ee/=:ss"

s1 = "mmmmm m nnnnn y&friend&Paul has heavy hats! &"
s2 = "my frie n d Joh n has ma n y ma n y frie n ds n&"
mix(s1, s2) # --> "1:mmmmmm/=:nnnnnn/1:aaaa/1:hhh/2:yyy/2:dd/2:ff/2:ii/2:rr/=:ee/=:ss"

s1="Are the kids at home? aaaaa fffff"
s2="Yes they are here! aaaaa fffff"
mix(s1, s2) # --> "=:aaaaaa/2:eeeee/=:fffff/1:tt/2:rr/=:hh"

# Note for Swift, R, PowerShell
# The prefix =: is replaced by E:

s1 = "mmmmm m nnnnn y&friend&Paul has heavy hats! &"
s2 = "my frie n d Joh n has ma n y ma n y frie n ds n&"
mix(s1, s2) # --> "1:mmmmmm/E:nnnnnn/1:aaaa/1:hhh/2:yyy/2:dd/2:ff/2:ii/2:rr/E:ee/E:ss"

Solution

Incorrect password!

Hash Table (Hash Map)

Two Sum

Description

https://www.codewars.com/kata/52c31f8e6605bcc646000082/

Write a function that takes an array of numbers (integers for the tests) and a target number. It should find two different items in the array that, when added together, give the target value. The indices of these items should then be returned in a tuple / list (depending on your language) like so: (index1, index2).

For the purposes of this kata, some tests may have multiple answers; any valid solutions will be accepted.

The input will always be valid (numbers will be an array of length 2 or greater, and all of the items will be numbers; target will always be the sum of two different items from that array).

Based on: https://leetcode.com/problems/two-sum/

two_sum([1, 2, 3], 4) # returns (0, 2) or (2, 0)
two_sum([3, 2, 4], 6) # returns (1, 2) or (2, 1)

Solution

def two_sum(numbers, target):
    '''
    实现步骤:
        遍历数组:对于数组中的每一个元素,我们计算目标值与当前元素的差值。这个差值就是我们需要在数组中寻找的另一个元素。
        使用字典(哈希表):在遍历数组的过程中,我们将已经遍历过的元素及其对应的索引存储在字典中。这样我们可以快速检查之前是否已经遇到过所需的差值。
        检查匹配对:如果当前元素所对应的差值已经在字典中存在,那么我们就找到了这两个元素,可以直接返回它们的索引。
    '''
    lookup = {}
    for i, num in enumerate(numbers):
        difference = target - num
        if difference in lookup:
            return (lookup[difference], i)
        lookup[num] = i

Sum of Paris

Description

https://www.codewars.com/kata/54d81488b981293527000c8f/

Given a list of integers and a single sum value, return the first two values (parse from the left please) in order of appearance that add up to form the sum.

If there are two or more pairs with the required sum, the pair whose second element has the smallest index is the solution.

sum_pairs([11, 3, 7, 5],         10)
#              ^--^      3 + 7 = 10
== [3, 7]

sum_pairs([4, 3, 2, 3, 4],         6)
#          ^-----^         4 + 2 = 6, indices: 0, 2 *
#             ^-----^      3 + 3 = 6, indices: 1, 3
#                ^-----^   2 + 4 = 6, indices: 2, 4
#  * the correct answer is the pair whose second value has the smallest index
== [4, 2]

sum_pairs([0, 0, -2, 3], 2)
#  there are no pairs of values that can be added to produce 2.
== None/nil/undefined (Based on the language)

sum_pairs([10, 5, 2, 3, 7, 5],         10)
#              ^-----------^   5 + 5 = 10, indices: 1, 5
#                    ^--^      3 + 7 = 10, indices: 3, 4 *
#  * the correct answer is the pair whose second value has the smallest index
== [3, 7]

Negative numbers and duplicate numbers can and will appear.

NOTE: There will also be lists tested of lengths upwards of 10,000,000 elements. Be sure your code doesn’t time out.

Solution

Incorrect password!

Stack and Queue

Directions Reduction

Description

https://www.codewars.com/kata/550f22f4d758534c1100025a/

Once upon a time, on a way through the old wild mountainous west,… … a man was given directions to go from one point to another. The directions were “NORTH”, “SOUTH”, “WEST”, “EAST”. Clearly “NORTH” and “SOUTH” are opposite, “WEST” and “EAST” too.

Going to one direction and coming back the opposite direction right away is a needless effort. Since this is the wild west, with dreadful weather and not much water, it’s important to save yourself some energy, otherwise you might die of thirst!

How I crossed a mountainous desert the smart way.

The directions given to the man are, for example, the following (depending on the language):

["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"].
or
{ "NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST" };
or
[North, South, South, East, West, North, West]

You can immediately see that going “NORTH” and immediately “SOUTH” is not reasonable, better stay to the same place! So the task is to give to the man a simplified version of the plan. A better plan in this case is simply:

["WEST"]
or
{ "WEST" }
or
[West]

Other examples:

In ["NORTH", "SOUTH", "EAST", "WEST"], the direction "NORTH" + "SOUTH" is going north and coming back right away.

The path becomes ["EAST", "WEST"], now "EAST" and "WEST" annihilate each other, therefore, the final result is [] (nil in Clojure).

In ["NORTH", "EAST", "WEST", "SOUTH", "WEST", "WEST"], "NORTH" and "SOUTH" are not directly opposite but they become directly opposite after the reduction of "EAST" and WEST" so the whole path is reducible to ["WEST", "WEST"].

Task Write a function dirReduc which will take an array of strings and returns an array of strings with the needless directions removed (W<->E or S<->N side by side).

The Haskell version takes a list of directions with data Direction = North | East | West | South.

The Clojure version returns nil when the path is reduced to nothing.

The Rust version takes a slice of enum Direction {North, East, West, South}.

See more examples in “Sample Tests:”

Notes

Not all paths can be made simpler. The path ["NORTH", "WEST", "SOUTH", "EAST"] is not reducible. "NORTH" and "WEST", "WEST" and "SOUTH", "SOUTH" and "EAST" are not directly opposite of each other and can’t become such. Hence the result path is itself : ["NORTH", "WEST", "SOUTH", "EAST"].

Solution

Incorrect password!

The Supermarket Queue

Description

https://www.codewars.com/kata/57b06f90e298a7b53d000a86

There is a queue for the self-checkout tills at the supermarket. Your task is write a function to calculate the total time required for all the customers to check out!

input

  • customers: an array of positive integers representing the queue. Each integer represents a customer, and its value is the amount of time they require to check out.
  • n: a positive integer, the number of checkout tills.

output: The function should return an integer, the total time required.

Important: Please look at the examples and clarifications below, to ensure you understand the task correctly :)

Examples

queue_time([5,3,4], 1)
# should return 12
# because when n=1, the total time is just the sum of the times

queue_time([10,2,3,3], 2)
# should return 10
# because here n=2 and the 2nd, 3rd, and 4th people in the 
# queue finish before the 1st person has finished.

queue_time([2,3,10], 2)
# should return 12

Clarifications

  • There is only ONE queue serving many tills, and
  • The order of the queue NEVER changes, and
  • The front person in the queue (i.e. the first element in the array/list) proceeds to a till as soon as it becomes free.

N.B. You should assume that all the test input will be valid, as specified above.

P.S. The situation in this kata can be likened to the more-computer-science-related idea of a thread pool, with relation to running multiple processes at the same time: https://en.wikipedia.org/wiki/Thread_pool

Solution

Incorrect password!

Algorithms

Dynamic programming

Expressions Matter

Description

https://www.codewars.com/kata/5ae62fcf252e66d44d00008e/python

Given three integers a, b, and c, return the largest number obtained after inserting the operators +, *, and parentheses (). In other words, try every combination of a, b, and c with the operators, without reordering the operands, and return the maximum value.

Example With the numbers 1, 2, and 3, here are some possible expressions:

  • 1 * (2 + 3) = 5
  • 1 * 2 * 3 = 6
  • 1 + 2 * 3 = 7
  • (1 + 2) * 3 = 9

The maximum value that can be obtained is 9.

Notes

  • The numbers are always positive, in the range 1 ≤ a, b, c ≤ 10.
  • You can use the same operation more than once.
  • It is not necessary to use all the operators or parentheses.
  • You cannot swap the operands. For example, with the given numbers, you cannot get the expression (1 + 3) * 2 = 8.

Input and Output Examples

  • expressionsMatter(1, 2, 3) ==> 9, because (1 + 2) * 3 = 9.
  • expressionsMatter(1, 1, 1) ==> 3, because 1 + 1 + 1 = 3.
  • expressionsMatter(9, 1, 1) ==> 18, because 9 * (1 + 1) = 18.

Solution

Incorrect password!

Complexity

Gap in Primes

Description

https://www.codewars.com/kata/561e9c843a2ef5a40c0000a4/python

The prime numbers are not regularly spaced. For example from 2 to 3 the gap is 1. From 3 to 5 the gap is 2. From 7 to 11 it is 4. Between 2 and 50 we have the following pairs of 2-gaps primes: 3-5, 5-7, 11-13, 17-19, 29-31, 41-43

A prime gap of length n is a run of n-1 consecutive composite numbers between two successive primes (see: http://mathworld.wolfram.com/PrimeGaps.html).

We will write a function gap with parameters:

  • g (integer >= 2) which indicates the gap we are looking for
  • m (integer > 2) which gives the start of the search (m inclusive)
  • n (integer >= m) which gives the end of the search (n inclusive)

In the example above gap(2, 3, 50) will return [3, 5] or (3, 5) or {3, 5} which is the first pair between 3 and 50 with a 2-gap.

So this function should return the first pair of two prime numbers spaced with a gap of g between the limits m, n if these numbers exist otherwise nil or null or Noneor Nothing (or…` depending on the language).

  • In such a case (no pair of prime numbers with a gap of g)
  • In C: return [0, 0]
  • In C++, Lua, COBOL: return {0, 0}.
  • In F#: return [||].
  • In Kotlin, Dart and Prolog: return [].
  • In Pascal: return Type TGap (0, 0).

Examples:

  • gap(2, 5, 7) –> [5, 7] or (5, 7) or {5, 7}
  • gap(2, 5, 5) –> nil. In C++ {0, 0}. In F# [||]. In Kotlin, Dart and Prolog return []`
  • gap(4, 130, 200) –> [163, 167] or (163, 167) or {163, 167}

([193, 197] is also such a 4-gap primes between 130 and 200 but it’s not the first pair)

  • gap(6,100,110) –> nil or {0, 0} or ... : between 100 and 110 we have 101, 103, 107, 109 but 101-107is not a 6-gap because there is 103 in between and 103-109 is not a 6-gap because there is 107 in between.
  • You can see more examples of return in Sample Tests.

Note for Go: For Go: nil slice is expected when there are no gap between m and n. Example: gap(11,30000,100000) –> nil

Solution

Incorrect password!