Machine Coding Problem

Mentions & Tagging System

macoAllsocialstring-parsingnotifications
Commonly Asked By:MetaTwitterSlackLinkedIn

Functional Scope (In-Scope)

  • Token Parse and Extract Engine: Scans text strings using performance-optimized regex patterns to extract mention indicators.
  • Stateless Username ID Resolution: Cross-references parsed usernames against active user registries to map real IDs.
  • Mention Deduplication Rules: Suppresses repeated alarms to prevent duplicate notifications for single posts.
  • Trending Hashtag Index Aggregations: Periodically indexes tags and calculates trending weights over custom rolling time windows.

Explicit Boundaries (Out-of-Scope)

  • Rich Text Rendering layout wrappers: Omits in-app rich editors, syntax highlights, and markdown parser layout widgets.
  • Physical Push Delivery brokers: Simulates notification logs in-memory rather than integrating concrete Apple APNS or Firebase FCM gateways.

Production reference implementations demonstrating token parsing, username resolution, trend computation, and deduplicated notification routing in Java and Python:

// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

class Post {
    private final String id;
    private final String authorId;
    private final String content;
    private final long createdAtMs;
    private final Set<String> mentionedUserIds;
    private final Set<String> hashtags;

    public Post(String id, String authorId, String content, Set<String> mentionedUserIds, Set<String> hashtags) {
        this.id = id;
        this.authorId = authorId;
        this.content = content;
        this.createdAtMs = System.currentTimeMillis();
        this.mentionedUserIds = new HashSet<>(mentionedUserIds);
        this.hashtags = new HashSet<>(hashtags);
    }

    public String getId() { return id; }
    public String getAuthorId() { return authorId; }
    public String getContent() { return content; }
    public long getCreatedAtMs() { return createdAtMs; }
    public Set<String> getMentionedUserIds() { return Collections.unmodifiableSet(mentionedUserIds); }
    public Set<String> getHashtags() { return Collections.unmodifiableSet(hashtags); }
}

class MentionsTaggingService {
    private final ConcurrentHashMap<String, Post> posts = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, String> userRegistry = new ConcurrentHashMap<>(); // username -> userId
    private final ConcurrentHashMap<String, ConcurrentLinkedQueue<String>> hashtagIndex = new ConcurrentHashMap<>(); // hashtag -> list of postIds
    private final ConcurrentLinkedQueue<String> notificationLog = new ConcurrentLinkedQueue<>();
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    private static final Pattern MENTION_PATTERN = Pattern.compile("@([a-zA-Z0-9_]+)");
    private static final Pattern HASHTAG_PATTERN = Pattern.compile("#([a-zA-Z0-9_]+)");

    public void registerUser(String username, String userId) {
        rwLock.writeLock().lock();
        try {
            userRegistry.put(username.toLowerCase(), userId);
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    // Publish Post with Token Parsing & Notification dispatching
    public Post createPost(String authorId, String content) {
        String postId = UUID.randomUUID().toString();
        
        rwLock.readLock().lock();
        Set<String> mentionedUserIds;
        try {
            // Parse @mentions and #hashtags
            mentionedUserIds = parseMentions(content);
        } finally {
            rwLock.readLock().unlock();
        }

        Set<String> hashtags = parseHashtags(content);

        Post newPost = new Post(postId, authorId, content, mentionedUserIds, hashtags);
        posts.put(postId, newPost);

        // Populate Hashtag Index
        for (String tag : hashtags) {
            hashtagIndex.computeIfAbsent(tag.toLowerCase(), k -> new ConcurrentLinkedQueue<>()).add(postId);
        }

        // Deliver Deduplicated Mention Notifications
        for (String userId : mentionedUserIds) {
            triggerNotification(userId, postId);
        }

        return newPost;
    }

    // O(K log K) trending hashtags by active volume in window
    public List<Map.Entry<String, Long>> getTrendingHashtags(long windowMs, int topN) {
        long limitTime = System.currentTimeMillis() - windowMs;

        return hashtagIndex.entrySet().stream()
            .map(entry -> {
                long activeCount = entry.getValue().stream()
                    .map(posts::get)
                    .filter(Objects::nonNull)
                    .filter(post -> post.getCreatedAtMs() >= limitTime)
                    .count();
                return new AbstractMap.SimpleEntry<>(entry.getKey(), activeCount);
            })
            .filter(entry -> entry.getValue() > 0)
            .sorted((a, b) -> Long.compare(b.getValue(), a.getValue()))
            .limit(topN)
            .collect(Collectors.toList());
    }

    public Post getPost(String postId) {
        return posts.get(postId);
    }

    public List<String> getNotificationLog() {
        return new ArrayList<>(notificationLog);
    }

    private Set<String> parseMentions(String text) {
        Set<String> resolvedIds = new HashSet<>();
        Matcher matcher = MENTION_PATTERN.matcher(text);
        while (matcher.find()) {
            String username = matcher.group(1).toLowerCase();
            String userId = userRegistry.get(username);
            if (userId != null) {
                resolvedIds.add(userId); // Deduplicates automatically
            }
        }
        return resolvedIds;
    }

    private Set<String> parseHashtags(String text) {
        Set<String> hashtags = new HashSet<>();
        Matcher matcher = HASHTAG_PATTERN.matcher(text);
        while (matcher.find()) {
            String tag = matcher.group(1).toLowerCase();
            hashtags.add(tag); // Deduplicates automatically
        }
        return hashtags;
    }

    private void triggerNotification(String userId, String postId) {
        String logEntry = "NOTIFY -> User: " + userId + " was mentioned in Post: " + postId;
        notificationLog.offer(logEntry);
        System.out.println(logEntry);
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("=== JAVA MENTIONS & TAGGING DEMO ===");
        MentionsTaggingService service = new MentionsTaggingService();

        // Register active platform users
        service.registerUser("Alice", "user_101");
        service.registerUser("Bob", "user_102");
        service.registerUser("Charlie", "user_103");

        // Alice publishes a post mentioning Bob and Charlie
        System.out.println("Alice publishes a post...");
        Post post1 = service.createPost("user_101", "Hey @Bob and @Charlie! Check this out! #coding #systemdesign");
        
        System.out.println("Post ID: " + post1.getId());
        System.out.println("Mentioned User IDs: " + post1.getMentionedUserIds());
        System.out.println("Hashtags extracted: " + post1.getHashtags());

        // Bob publishes a post with design tags
        System.out.println("\nBob publishes a post...");
        Post post2 = service.createPost("user_102", "Working on a new LLD problem. #coding #java");

        // Check trending hashtags over last 1 minute
        System.out.println("\nFetching trending hashtags...");
        List<Map.Entry<String, Long>> trends = service.getTrendingHashtags(60000, 5);
        for (Map.Entry<String, Long> trend : trends) {
            System.out.println(" - Tag: #" + trend.getKey() + " | Count: " + trend.getValue());
        }

        System.out.println("\nNotification Logs:");
        System.out.println(service.getNotificationLog());

        System.out.println("=== END OF DEMO ===");
    }
}