Zomato SDE interview | Machine coding Alarm Clock

Anonymous User
592
Dec 22, 2024
Dec 22, 2024

Current : SDE-2 with ~4 years of experience.

Design an alarm clock

Alarm clock should have the following functions
AddAlarm(time)
DeleteAlarm(time)
UpdateAlarm(oldtime, newtime)
Snooze(time, delaytime)

Write a program, on matching alarm times
system should Print "Wake Up".

Solution :

package main

import (
	"fmt"
	"time"
)

type AlarmClock struct {
	alarms map[string]time.Time
}

// NewAlarmClock creates a new AlarmClock instance.
func NewAlarmClock() *AlarmClock {
	return &AlarmClock{
		alarms: make(map[string]time.Time),
	}
}

// AddAlarm adds a new alarm to the clock.
func (ac *AlarmClock) AddAlarm(label string, alarmTime time.Time) {
	ac.alarms[label] = alarmTime
	fmt.Printf("Added alarm '%s' at %s\n", label, alarmTime.Format("15:04:05"))
}

// DeleteAlarm deletes an alarm from the clock.
func (ac *AlarmClock) DeleteAlarm(label string) {
	if _, exists := ac.alarms[label]; exists {
		delete(ac.alarms, label)
		fmt.Printf("Deleted alarm '%s'\n", label)
	} else {
		fmt.Printf("Alarm '%s' does not exist\n", label)
	}
}

// UpdateAlarm updates an existing alarm to a new time.
func (ac *AlarmClock) UpdateAlarm(label string, newTime time.Time) {
	if _, exists := ac.alarms[label]; exists {
		ac.alarms[label] = newTime
		fmt.Printf("Updated alarm '%s' to %s\n", label, newTime.Format("15:04:05"))
	} else {
		fmt.Printf("Alarm '%s' does not exist\n", label)
	}
}

// Snooze snoozes an alarm by adding a delay.
func (ac *AlarmClock) Snooze(label string, delay time.Duration) {
	if alarmTime, exists := ac.alarms[label]; exists {
		newTime := alarmTime.Add(delay)
		ac.alarms[label] = newTime
		fmt.Printf("Snoozed alarm '%s' to %s\n", label, newTime.Format("15:04:05"))
	} else {
		fmt.Printf("Alarm '%s' does not exist\n", label)
	}
}

// Start checks for matching alarm times and prints "Wake Up".
func (ac *AlarmClock) Start() {
	for {
		for label, alarmTime := range ac.alarms {
			if time.Now().After(alarmTime) {
				fmt.Printf("Wake Up! Alarm '%s' triggered at %s\n", label, alarmTime.Format("15:04:05"))
				delete(ac.alarms, label) // Remove the alarm after it triggers
			}
		}
		time.Sleep(1 * time.Second)
	}
}

func main() {
	ac := NewAlarmClock()

	// Add some alarms
	ac.AddAlarm("Morning Alarm", time.Now().Add(5*time.Second))
	ac.AddAlarm("Meeting Reminder", time.Now().Add(10*time.Second))

	// Update an alarm
	ac.UpdateAlarm("Morning Alarm", time.Now().Add(8*time.Second))

	// Snooze an alarm
	ac.Snooze("Meeting Reminder", 5*time.Second)

	// Start the alarm clock
	go ac.Start()

	// Keep the main function alive
	select {}
}

Follow ups:
1. Interview asked, you are running infine loop, can we improve this.
- I told we use a min heap, pull the next min alarm time, and sleep till next alarm.
- in case of update existing alarm or snooze, we have to reset the sleep time, if updated alarm becomes the new min time.
2. Feedback by interviewer : expectation was to use OS scheduler for next Trigger, instead of time.sleep(). interview told this is how the cron jobs work.

Guys help me understand : how the cron jobs work?, time.sleep is not used in crons?

Similar post i got : https://leetcode.com/discuss/interview-question/876976/amazon-sde-intern-phone-final-round

Comments (2)