Logger Rate Limiter

🏠 ⬅️ ➡️

Design a logger system that receives a stream of messages along with their timestamps. Each unique message should only be printed at most every 10 seconds (i.e. a message printed at timestamp t will prevent other identical messages from being printed until timestamp t + 10).

All messages will come in chronological order. Several messages may arrive at the same timestamp.

Implement the Logger class:

  • Logger() Initializes the logger object.
  • bool shouldPrintMessage(int timestamp, string message) Returns true if the message should be printed in the given timestamp, otherwise returns false.

Example 1:

Input [ "Logger ", "shouldPrintMessage ", "shouldPrintMessage ", "shouldPrintMessage ", "shouldPrintMessage ", "shouldPrintMessage ", "shouldPrintMessage "] [[], [1, "foo "], [2, "bar "], [3, "foo "], [8, "bar "], [10, "foo "], [11, "foo "]] Output [null, true, true, false, false, false, true]

Explanation Logger logger = new Logger(); logger.shouldPrintMessage(1, "foo "); // return true, next allowed timestamp for "foo " is 1 + 10 = 11 logger.shouldPrintMessage(2, "bar "); // return true, next allowed timestamp for "bar " is 2 + 10 = 12 logger.shouldPrintMessage(3, "foo "); // 3 < 11, return false logger.shouldPrintMessage(8, "bar "); // 8 < 12, return false logger.shouldPrintMessage(10, "foo "); // 10 < 11, return false logger.shouldPrintMessage(11, "foo "); // 11 >= 11, return true, next allowed timestamp for "foo " is 11 + 10 = 21

Constraints:

  • 0 <= timestamp <= 109
  • Every timestamp will be passed in non-decreasing order (chronological order).
  • 1 <= message.length <= 30
  • At most 104 calls will be made to shouldPrintMessage.

Note: This problem is from LeetCode.
Compiled
Executed
Correct
program main
    use Logger_mod
    implicit none

    type(Logger) :: logger
    integer :: i
    character(len=30) :: message
    integer :: timestamp

    ! Example 1
    call logger%shouldPrintMessage(1, "foo ")
    call logger%shouldPrintMessage(2, "bar ")
    call logger%shouldPrintMessage(3, "foo ")
    call logger%shouldPrintMessage(8, "bar ")
    call logger%shouldPrintMessage(10, "foo ")
    call logger%shouldPrintMessage(11, "foo ")

    ! Example 2
    do i = 1, 5
        call logger%shouldPrintMessage(i, "bar ")
    end do

    ! Example 3
    do i = 1, 5
        call logger%shouldPrintMessage(i, "foo ")
    end do

    ! Example 4
    do i = 1, 5
        call logger%shouldPrintMessage(i, "bar ")
    end do

    ! Example 5
    do i = 1, 5
        call logger%shouldPrintMessage(i, "foo ")
    end do

contains

subroutine print_result(result)
    logical, intent(in) :: result
    write(*, '(L1)') result
end subroutine print_result

end program main

module Logger_mod
    implicit none

    private
    public :: Logger

    type :: Logger
        private
        integer :: last_printed_timestamp = -1
        character(len=30), allocatable :: last_printed_message(:)
    contains
        procedure :: shouldPrintMessage
    end type Logger

contains

logical function shouldPrintMessage(self, timestamp, message) result(should_print)
    class(Logger), intent(inout) :: self
    integer, intent(in) :: timestamp
    character(len=*), intent(in) :: message
    integer :: i

    should_print = .false.

    if (timestamp > self%last_printed_timestamp + 10) then
        self%last_printed_timestamp = timestamp
        allocate(self%last_printed_message(1))
        self%last_printed_message(1) = message
        should_print = .true.
    else
        do i = 1, size(self%last_printed_message)
            if (self%last_printed_message(i) == message) then
                exit
            end if
        end do

        if (i > size(self%last_printed_message)) then
            self%last_printed_message = [self%last_printed_message, message]
            should_print = .true.
        end if
    end if

end function shouldPrintMessage

end module Logger_mod
Compiled
Executed
Correct
module Logger
    implicit none

    type :: Logger
        integer :: lastTimestamp = 0
        character(len=30) :: lastMessage = ""
    contains
        procedure :: shouldPrintMessage
    end type Logger

contains

    function shouldPrintMessage(self, timestamp, message) result(shouldPrint)
        class(Logger), intent(inout) :: self
        integer, intent(in) :: timestamp
        character(len=*), intent(in) :: message
        logical :: shouldPrint

        if (timestamp < self%lastTimestamp) then
            shouldPrint = .false.
        else if (timestamp == self%lastTimestamp .and. message == self%lastMessage) then
            shouldPrint = .false.
        else
            self%lastTimestamp = timestamp
            self%lastMessage = message
            shouldPrint = .true.
        end if
    end function shouldPrintMessage
end module Logger

program main
    use Logger
    implicit none

    type(Logger) :: logger
    integer :: timestamp, i
    character(len=30) :: message

    ! Examples
    call logger%shouldPrintMessage(1, "foo")
    call logger%shouldPrintMessage(2, "bar")
    call logger%shouldPrintMessage(3, "foo")
    call logger%shouldPrintMessage(8, "bar")
    call logger%shouldPrintMessage(10, "foo")
    call logger%shouldPrintMessage(11, "foo")

    ! Test cases
    do i = 1, 10
        timestamp = i * 10
        message = "message " // char(ichar('0') + i)
        call logger%shouldPrintMessage(timestamp, message)
    end do

    ! Print the results
    do i = 1, 10
        write (*,*) logger%shouldPrintMessage(i * 10, "message " // char(ichar('0') + i))
    end do
end program main
🌐 Data from online sources
class Logger:
    def __init__(self):
        self.message_timestamps = {}

    def shouldPrintMessage(self, timestamp: int, message: str) -> bool:
        if message not in self.message_timestamps or timestamp - self.message_timestamps[message] >= 10:
            self.message_timestamps[message] = timestamp
            return True
        return False

The algorithm initializes an empty map to store message timestamps. The shouldPrintMessage function takes input parameters timestamp and message. It checks if the message is in the map or not. If the message is not in the map or the difference between the given timestamp and the message's timestamp is greater than or equal to 10, it updates the message's timestamp in the map with the given timestamp, and the function returns true. If the difference is less than 10, the function returns false. This ensures that messages will only be printed at most every 10 seconds.

🌐 Data from online sources
#include <unordered_map>
#include <string>
using namespace std;

class Logger {
public:
    unordered_map<string, int> message_timestamps;

    Logger() {
    }

    bool shouldPrintMessage(int timestamp, string message) {
        if (!message_timestamps.count(message) || timestamp - message_timestamps[message] >= 10) {
            message_timestamps[message] = timestamp;
            return true;
        }
        return false;
    }
};

The algorithm initializes an empty map to store message timestamps. The shouldPrintMessage function takes input parameters timestamp and message. It checks if the message is in the map or not. If the message is not in the map or the difference between the given timestamp and the message's timestamp is greater than or equal to 10, it updates the message's timestamp in the map with the given timestamp, and the function returns true. If the difference is less than 10, the function returns false. This ensures that messages will only be printed at most every 10 seconds.