Skip to content

Instantly share code, notes, and snippets.

@InfiniteCoder01
Created August 12, 2025 16:23
Show Gist options
  • Select an option

  • Save InfiniteCoder01/23b5056883988e186d8fe7baf58d41f2 to your computer and use it in GitHub Desktop.

Select an option

Save InfiniteCoder01/23b5056883988e186d8fe7baf58d41f2 to your computer and use it in GitHub Desktop.

Revisions

  1. InfiniteCoder01 created this gist Aug 12, 2025.
    116 changes: 116 additions & 0 deletions challenge.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,116 @@
    #include <assert.h>
    #include <stddef.h>
    #include <stdbool.h>

    // Option implementation
    #define option(T) option_ ## T
    #define option_method(T, M) option_ ## T ## _ ## M
    #define option_genimpl(T) \
    typedef struct { \
    bool tag; \
    T value; \
    } option(T); \
    \
    option(T) option_method(T, some) (T value) {\
    return (option(T)) { \
    .tag = true, \
    .value = value, \
    }; \
    }\
    \
    option(T) option_method(T, none) () {\
    return (option(T)) { \
    .tag = false, \
    }; \
    }\
    \
    bool option_method(T, eq) (\
    option(T) lhs,\
    option(T) rhs\
    ) {\
    if (lhs.tag != rhs.tag) return false;\
    if (lhs.tag) return lhs.value == rhs.value;\
    return true;\
    }

    option_genimpl(size_t);

    // Trait impl
    #define impl_assoc(T, S, A) T ## _ ## S ## _ ## A
    #define impl_assoc2(T, S, A) impl_assoc(T, S, A)

    // Peekable
    #define peekable(T, I) peekable_ ## T ## _ ## I
    #define peekable_method(T, I, M) peekable_ ## T ## _ ## I ## _ ## M
    #define peekable_genimpl(T, I) \
    typedef struct { \
    T iter; \
    option(I) peeked; \
    } peekable(T, I);\
    \
    option(I) peekable_method(T, I, peek)(peekable(T, I) *self) {\
    if (!self->peeked.tag) {\
    self->peeked = impl_assoc(simple_iterator, T, next)(&self->iter);\
    }\
    \
    return self->peeked;\
    }\
    \
    option(I) impl_assoc2(simple_iterator, peekable(T, I), next)(peekable(T, I) *self) {\
    if (self->peeked.tag) {\
    option(I) tmp = self->peeked;\
    self->peeked = option_method(I, none)();\
    return tmp;\
    } else {\
    return impl_assoc(simple_iterator, T, next)(&self->iter);\
    }\
    }\
    \
    typedef I impl_assoc2(simple_iterator, peekable(T, I), item);\
    \
    peekable(T, I) iter_peekable(T iter) {\
    return (peekable(T, I)) {\
    .iter = iter,\
    .peeked = option_method(I, none)(),\
    };\
    }

    // Iota implementation
    typedef struct {
    size_t field0;
    } iota;

    iota iota_new() {
    return (iota) {
    .field0 = 0,
    };
    }

    option_size_t impl_assoc(simple_iterator, iota, next)(iota *self) {
    size_t prev = self->field0;
    self->field0 = prev + 1;
    return option_size_t_some(prev);
    }

    typedef size_t impl_assoc(simple_iterator, iota, item);

    peekable_genimpl(iota, size_t)

    // Main
    #include <stdio.h>
    int main() {
    iota iota = iota_new();
    assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(0)));
    assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(1)));
    assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(2)));
    assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(3)));

    peekable(iota, size_t) peekable_iota = iter_peekable(iota);
    assert(option_size_t_eq(peekable_method(iota, size_t, peek)(&peekable_iota), option_size_t_some(4)));
    assert(option_size_t_eq(peekable_method(iota, size_t, peek)(&peekable_iota), option_size_t_some(4)));
    assert(option_size_t_eq(peekable_method(iota, size_t, peek)(&peekable_iota), option_size_t_some(4)));

    assert(option_size_t_eq(impl_assoc2(simple_iterator, peekable(iota, size_t), next)(&peekable_iota), option_size_t_some(4)));
    assert(option_size_t_eq(impl_assoc2(simple_iterator, peekable(iota, size_t), next)(&peekable_iota), option_size_t_some(5)));
    assert(option_size_t_eq(impl_assoc2(simple_iterator, peekable(iota, size_t), next)(&peekable_iota), option_size_t_some(6)));
    }
    70 changes: 70 additions & 0 deletions challenge.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,70 @@
    pub trait SimpleIterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    fn peekable(self) -> Peekable<Self, Self::Item>
    where
    Self: Sized,
    {
    Peekable {
    iter: self,
    peeked: None,
    }
    }
    }

    pub struct Peekable<T, I> {
    iter: T,
    peeked: Option<I>,
    }

    impl<I: Clone, T: SimpleIterator<Item = I>> Peekable<T, I> {
    pub fn peek(&mut self) -> Option<I> {
    if self.peeked.is_none() {
    self.peeked = self.iter.next();
    }
    self.peeked.clone()
    }
    }

    impl<I, T: SimpleIterator<Item = I>> SimpleIterator for Peekable<T, I> {
    type Item = T::Item;
    fn next(&mut self) -> Option<T::Item> {
    match &self.peeked {
    Some(_) => std::mem::replace(&mut self.peeked, None),
    None => self.iter.next(),
    }
    }
    }

    pub struct Iota(usize);

    impl Iota {
    pub fn new() -> Self {
    Iota(0)
    }
    }

    impl SimpleIterator for Iota {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
    let prev = self.0;
    self.0 = prev + 1;
    Some(prev)
    }
    }

    fn main() {
    let mut iota = Iota::new();
    assert_eq!(iota.next(), Some(0));
    assert_eq!(iota.next(), Some(1));
    assert_eq!(iota.next(), Some(2));
    assert_eq!(iota.next(), Some(3));

    let mut peekable_iota = iota.peekable();
    assert_eq!(peekable_iota.peek(), Some(4));
    assert_eq!(peekable_iota.peek(), Some(4));
    assert_eq!(peekable_iota.peek(), Some(4));
    assert_eq!(peekable_iota.next(), Some(4));
    assert_eq!(peekable_iota.next(), Some(5));
    assert_eq!(peekable_iota.next(), Some(6));
    }