00_Getting Started

Template

%% Commands for TeXCount
%TC:macro \cite [option:text,text]
%TC:macro \citep [option:text,text]
%TC:macro \citet [option:text,text]
%TC:envir table 0 1
%TC:envir table* 0 1
%TC:envir tabular [ignore] word
%TC:envir displaymath 0 word
%TC:envir math 0 word
%TC:envir comment 0 0

\documentclass[sigconf]{acmart}
\citestyle{acmauthoryear}    
%%
%% \BibTeX command to typeset BibTeX logo in the docs
\AtBeginDocument{%
  \providecommand\BibTeX{{%
    Bib\TeX}}}

\setcopyright{rightsretained}
\copyrightyear{2025}
\acmYear{2025}
\acmConference{SIGGRAPH Appy Hour '25}{August 10-14, 2025}{Vancouver, BC, Canada}
\acmBooktitle{Special Interest Group on Computer Graphics and Interactive Techniques Conference Appy Hour (SIGGRAPH Appy Hour '25), August 10-14, 2025}
\acmDOI{10.1145/3721260.3733980}
\acmISBN{979-8-4007-1552-5/2025/08}

\begin{document}

%%
%% The "title" command has an optional parameter,
%% allowing the author to define a "short title" to be used in page headers.
\title{ScavengeAR: From Licensing Fees to Free — Rebuilding Mobile AR with Unity-Native Tools}
\author{Victor Leung}
\email{thevictor2225@gmail.com}
\orcid{0009-0000-0600-668X}
%%\affiliation{%
%%  \institution{Independent Developer}
%%  \city{California}
%%  \state{Mountain View}
%%  \country{USA}


\begin{abstract}
ScavengeAR, an augmented reality creature-collecting mobile game, returns to SIGGRAPH in 2025 after a six-year hiatus, featuring a modernized tech stack and refined gameplay. The reboot preserves the core player experience while eliminating costly third-party dependencies.
\end{abstract}

\begin{teaserfigure}
  \includegraphics[width=\textwidth]{scavengear_teaserbanner.jpg}
  \caption{Testing ScavengeAR’s 2017 mobile build in Unity}
  \Description{A person holds a smartphone displaying an augmented reality (AR) creature over a colorful marker pattern. Behind the phone, a computer screen shows the same marker being processed in Unity with a grid of image target icons. The AR creature is a teal, cartoon-style robot with yellow antlers and big eyes, floating above text describing SIGGRAPH’s AR showcase.}
  \label{fig:teaser}
\end{teaserfigure}

%%\received{20 February 2007}
%%\received[revised]{12 March 2009}
%%\received[accepted]{5 June 2009}

\maketitle

\section{Introduction}
ScavengeAR was SIGGRAPH's official AR mobile app from 2017 to 2019, offering attendees an engaging augmented reality experience and providing Luddy School of Informatics, Computing, and Engineering, Indiana University Indianapolis students with hands-on opportunities in interactive media development. 

In the game, SIGGRAPH attendees choose a role — Artist, Scientist, or Educator — and explore the conference venue to discover printed image targets that, when scanned through the app, spawn 3D AR creatures into their physical surroundings. Like a digital safari, players use the in-app camera to photograph each creature, capturing them into a personal library. New creatures are released each day of the conference, encouraging daily exploration and unlocking new layers of narrative and prize opportunities over time. In addition, the attendee has their own creature based on their role, which encourages real interactions with other attendees in order to catch all the creatures for the best prizes. 
\begin{figure}[ht]
  \centering
  \includegraphics[width=\linewidth]{scavengear_threephoneview.PNG}
  \caption{ScavengeAR 2019 Los Angeles Convention Center map screen, profile screen, and role share screen.}
  \label{fig:teaser}
\end{figure}
\section{Motivation}




ScavengeAR ran from 2017-2019, with over a thousand daily active users during the conference. In 2020, the Covid Pandemic stopped in-person activity for a number of years, and effectively halted the app's development, leaving it in a deprecated state.         

In 2025, a small volunteer team undertook a comprehensive refactoring of ScavengeAR to improve its maintainability and accessibility, in order to revive the spirit of the app to a modern audience.

\section{Technical Approach}

The original version of ScavengeAR was built using Unity 2018 and Vuforia 8 - a robust and accessible image tracking solution that was among the most practical options for AR based 2D markers at the time. Vuforia’s artist-friendly pipeline utilized a parent-child GameObject hierarchy within a single-scene architecture, allowing low-code AR development and rapid prototyping in a pre-ARKit/ARCore standardization era. However, Vuforia also required licensing fees for production deployment and cloud-hosted image target storage.

For the 2025 relaunch, ScavengeAR was refactored to using Unity 2022 and AR Foundation 5 — Unity’s native, cross-platform AR framework built on top of ARKit and ARCore — to support lightweight, offline 2D image tracking and reduce long-term costs, build size, and technical dependencies.

Migrating to AR Foundation required a shift to its modular, multi-scene, prefab-driven architecture. While we traded Vuforia’s simplicity, the new system offered improved performance management and a clearer separation of concerns. AR Foundation also supports full in-editor XR simulation—replacing webcam-based workflows—which proved essential for rapidly iterating on the modernized photo capture experience.

Originally built using GameSparks for backend services and a licensed data binding plugin for UI management, we replaced GameSparks with Unity's built-in serialization for offline data handling, and transitioned to an open-source MVVM Toolkit. These changes not only further reduced external dependencies and licensing costs but also simplified the codebase, making it more approachable for new contributors.

While the core functionality remains consistent with previous iterations, this overhaul ensures that ScavengeAR can continue to be a sustainable and educational project. By leveraging Unity's modern XR capabilities and open-source tools, we've positioned the app for easier updates and potential future enhancements, aligning with our goal of providing valuable learning experiences for students and enjoyable interactions for conference attendees.

\section{Art and Design}
\begin{figure}[ht]
  \centering
  \includegraphics[width=\linewidth]{scavengear_newcreatures.jpg}
  \caption{New creatures for ScavengeAR}
  \label{fig:teaser}
\end{figure}

Luddy School of Informatics, Computing, and Engineering, Indiana University Indianapolis students has historically contributed original 3D creature designs for each iteration of ScavengeAR, and they return once again with a new cast of characters. This year’s creatures were developed using a traditional animation and visual effects pipeline, continuing the project’s tradition of experimenting with new styles and creative direction in each version.

For the user experience, we retained the core interaction flow from ScavengeAR 2019, which has been iteratively tested and refined through multiple conference deployments. While earlier versions of the app featured playful mini-games like Triviatron and Sigglet Falls, these proved non-essential to the primary gameplay loop. Instead, our focus shifted to improving the AR photo-taking experience—updating the camera overlay to better suit modern tall-screen phones, adding a tactile shutter animation, and introducing a polaroid-style fadeout to reinforce the analog camera motif.

\section{Future Work}
\begin{figure}[ht]
  \centering
  \includegraphics[width=\linewidth]{scavengear-2018creature.png}
  \caption{A 2018 ScavengeAR creature, originally featured at the SIGGRAPH Studio venue in the Vancouver Convention Centre, shown here without the mobile user interface.}
  \label{fig:teaser}
\end{figure}
Mobile AR has historically offered a more accurate representation of augmented reality by leveraging the raw camera feed to detect physical markers in the environment. At the time, Mixed Reality headsets restricted access to raw passthrough video, limiting similar capabilities. That trend is now shifting, with newer headsets offering improved access to video passthrough.

As we look ahead, a key challenge will be unifying the user experience (UX), user interface (UI), and interaction patterns across both mobile and headset-based platforms. With our latest refactor, we’re well-positioned to support both moving forward.

\begin{acks}
ScavengeAR could not have been created without the significant contributions of: Casey Kwock, Victor Leung, Thach Nguyen, Louie Whitesel, and Zeb Wood. Additionally, we appreciate the supporting contributions of Jose Garrido, Spencer Hayes, Alli Johnson, and Andy Wang.

We also thank the many volunteers who helped bring previous versions of the game to life, as well as the donors whose generosity helped cover software licensing costs throughout the project’s development.
Finally, we extend our gratitude to the players across SIGGRAPH conferences whose enthusiasm and feedback have continually shaped the experience.
\end{acks}

%%
%% The next two lines define the bibliography style to be used, and
%% the bibliography file.
%%\bibliographystyle{ACM-Reference-Format}
%%\bibliography{sample-base}


%%
%% If your work has an appendix, this is the place to put it.
\appendix




\end{document}
\endinput

coding_interview_steps.jpeg


which is to be published in siggraphappyhour25 to The ACM Publishing System (TAPS). The system will be sending 3 reminders within 120 HRS of sending the first notification to upload inputs of your paper. Please upload your files within this time frame, to avoid support delays due to last minute rush.

Please use this link to upload the zip file of your paper for processing, the instructions regarding how to prepare your zip file for submission are posted at the top of the page:

http://camps.aptaracorp.com/AuthorDashboard/dashboard.html?key=0&val=3645720d-3532-11f0-ada9-16bb50361d1f

Note: Please make sure to verify your paper details from the option “CHECK PAPER DETAILS” provided at the mentioned link, before you upload the zip file, as that information will be printed in your paper?s HTML version.

In addition, any supplements/videos associated with your paper will need to be uploaded using a separate link mentioned below:

https://cms.acm.org/artifactSubmission/fileUpload.cfm?parent=50565B0300&id=525550020B0B51

Should you have any issues preparing or uploading the zip file for your paper, please lodge a ticket using “Contact Support” form on your TAPS dashboard; If you face any problem while adding the ticket, then you can also contact confsupport@aptaracorp.com for assistance.

Sincerely,
ACM Production

***************************************************************************
Do not reply to this message as emails are not monitored at this account.
***************************************************************************

https://github.com/mdmzfzl/NeetCode-Solutions

def solve_problem(inputs):
    # Step 1: Understand the Problem
    # - Parse inputs and outputs.
    # - Clarify constraints (e.g., time, space).
    # - Identify edge cases.

    # Step 2: Plan and Design
    # - Think about the brute-force approach.
    # - Optimize: Can you use dynamic programming, divide & conquer, etc.?
    # - Choose the appropriate data structures (e.g., arrays, hashmaps, heaps).
    
    # Step 3: Implement the Solution
    # - Use helper functions for modularity.
    # - Write clear, well-commented code.
    
    def helper_function(args):
        # Optional: For recursion, BFS, DFS, etc.
        pass

    # Main logic
    result = None  # Initialize result or output variable.
    
    # Example logic
    # for num in inputs:
    #    result += num  # Or other computations.

    return result

# Driver code (for testing locally)
if __name__ == "__main__":
    inputs = []  # Replace with example test cases.
    print(solve_problem(inputs))

Understanding BIG O Calculations

Big O notation is a way to describe how the algorithm grow as the input size increases. Two things it considers: 

1. Basic Idea

2. Common Time Complexities

big_o_graph_annotated.png

In order of least dominating term O(1) to most dominating term (the one that grows the fastest)

3. Understanding Through Examples

Constant Time – O(1)

def get_first_element(lst):
    return lst[0]  

Regardless of list size, only one operation is performed.

Linear Time – O(n)

def find_max(lst):
    max_val = lst[0]
    for num in lst:
        if num > max_val:
            max_val = num
    return max_val

In the find_max function, every element is inspected once, so the time grows linearly with the list size.

Quadratic Time – O(n²)

def print_all_pairs(lst):
    for i in range(len(lst)):
        for j in range(len(lst)):
            print(lst[i], lst[j])

Here, for each element, you’re iterating over the entire list, leading to a quadratic number of comparisons.

4. Why Big O Matters

5. Space Complexity

6. Visualizing Growth Rates

Imagine a graph where the x-axis is the input size and the y-axis is the time taken:

7. Combining big-o

When you have different parts of an algorithm with their own complexities, combining them depends on whether they run sequentially or are nested within each other.

1. Sequential Operations

If you perform one operation after the other, you add their complexities. For example, if one part of your code is O(n) and another is O(n²), then the total time is:

This is because, as n grows, the O(n²) term dominates and the lower-order O(n) becomes negligible.

def sequential_example(nums):
    # First part: O(n)
    for num in nums:
        print(num)

    # Second part: O(n²)
    for i in range(len(nums)):
        for j in range(len(nums)):
            print(nums[i], nums[j])

Here, the overall time complexity is O(n) + O(n²), which simplifies to O(n²).

2. Nested Operations

If one operation is inside another (nested loops), you multiply their complexities. For example, if you have an outer loop that runs O(n) times and an inner loop that runs O(n) times for each iteration, then the total time is:

def nested_example(nums):
    for i in range(len(nums)):          # O(n)
        for j in range(len(nums)):      # O(n) for each i
            print(nums[i], nums[j])
This nested structure gives you O(n²) overall.

3. Combining Different Parts

In real problems, your code might have a mix of sequential and nested parts.

The key idea is:

  1. Add the complexities for sequential parts.

  2. Multiply the complexities for nested parts.

  3. Drop the lower-order terms and constant factors.

When adding complexities, the dominating term (the one that grows the fastest) is the one that determines the overall Big O notation.

Examples:

def combined_example(arr):
    # Sequential part: Loop that processes each element.
    # This loop runs O(n) times.
    for x in arr:
        print(x)  # O(1) operation per element.

    # Nested part: For each element in arr, loop over arr again.
    # The inner loop is nested within the outer loop, giving O(n) * O(n) = O(n²) operations.
    for x in arr:
        for y in arr:
            print(x, y)  # O(1) operation per inner loop iteration.

# If we call combined_example, the overall complexity is:
# O(n) [from the first loop] + O(n²) [from the nested loops].
# For large n, O(n²) dominates O(n), so we drop the lower-order term and constant factors,
# and the overall time complexity is O(n²).

if __name__ == "__main__":
    sample_list = [1, 2, 3, 4, 5]
    combined_example(sample_list)
# Binary search on a sorted list
def binary_search(arr, target):
    low, high = 0, len(arr) - 1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1

# Outer loop processes each query, each using binary search
def search_all(sorted_arr, queries):
    results = []
    for query in queries:         # O(n) if queries contains n items
        index = binary_search(sorted_arr, query)  # O(log n)
        results.append(index)
    return results

if __name__ == '__main__':
    # Assume this list is already sorted
    sorted_arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    # List of queries (if its size is roughly n, overall complexity is O(n log n))
    queries = [3, 7, 10]
    print("Search results:", search_all(sorted_arr, queries))

This example demonstrates how nested operations (a loop with an inner binary search) yield an O(n log n) algorithm.

Special Note: If using python sort method, it uses TimSort which worse case is O(n log n)

Loops

loops-to-use.png

🟢 Standard

Use when you want to loop directly over the items (values only).

Input Example Output
["apple", "banana"] for fruit in ["apple", "banana"]: print(fruit) apple banana
"hi" for char in "hi": print(char) h i
{ "a": 1, "b": 2 } for key in {"a": 1, "b": 2}: print(key) a b
dict.items() for k, v in {"a": 1}.items(): print(k, v) a 1

🔷 RANGE LOOPS

Use when you need to count, index, or control the steps of iteration.

Input Example Output
range(3) for i in range(3): print(i) 0 1 2
range(2, 5) for i in range(2, 5): print(i) 2 3 4
range(0, 6, 2) for i in range(0, 6, 2): print(i) 0 2 4
range(3, 0, -1) for i in range(3, 0, -1): print(i) 3 2 1
range(len(list)) for i in range(len(fruits)): print(fruits[i]) values in fruits


🟣 ENUMERATE LOOPS

Use when you want both index and value from a list or iterable.

Input Example Output
["x", "y"] for i, v in enumerate(["x", "y"]): print(i, v) 0 x 1 y
["a", "b", "c"] for i, letter in enumerate(["a", "b", "c"]): ... 0 a 1 b 2 c

🧱 NESTED LOOPS 

Loop Type Input Example Output
🔷 Range range(2), range(2) for i in range(2): for j in range(2): print(i, j) 0 0, 0 1, 1 0, 1 1
🔷 Range 2D array (matrix) by index for i in range(len(matrix)):for j in range(len(matrix[0])): Access each matrix[i][j]
🔷 Range All pairs in list for i in range(len(nums)):for j in range(i+1, len(nums)): Pairs (i, j)
🟣 Enumerate List of lists (2D grid) for i, row in enumerate(grid):for j, val in enumerate(row): (i, j, val) per cell
🟢 Normal List of lists (values only) for row in matrix:for val in row: print(val) Each cell value
🟢 Normal Two arrays (cross product) for a in ["a", "b"]:for n in ["1", "2"]: print(a, n) a 1, a 2, b 1, b 2


1. ✅ Standard for loop

Use when you want to iterate over items in a list, set, or string.

colors = ['red', 'green', 'blue']
for color in colors:
    print(color)

2. ✅ enumerate() loop

Use when you need both the index and the value.

for i, color in enumerate(colors):
    print(i, color)

3. ✅ range() loop

Use when you want to:



4. ✅ while loop

Use when:

x = 0
while x < 5:
    print(x)
    x += 1

📌 Warning: Always make sure the condition will eventually become False or you'll get an infinite loop!


🧠 When to Use Which?

Loop Type When to Use
for item in list Clean, readable, item-based loops
enumerate() Index + value
range() Loop by number or index, brute-force logic
while Loop while a condition is true (uncertain end)

Optional Daily Practice Prompts

Want to write one of each daily?


Want me to add this to your daily fundamentals checklist or export it as a mini Anki flashcard set or markdown file you can keep open?

OOP for Python

Absolutely! Here's a practical set of Python OOP code examples for each item in your 🧱 Object-Oriented Programming (OOP) checklist — perfect for review or muscle-memory practice.


🧱 Object-Oriented Programming (OOP) in Python — With Code Examples


1. Create a class with __init__()

class Dog:
    def __init__(self, name):
        self.name = name

d = Dog("Fido")
print(d.name)  # Fido

2. Add a method to the class

class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        return f"{self.name} says woof!"

d = Dog("Rex")
print(d.bark())  # Rex says woof!

3. Use @property for a read-only attribute

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def area(self):
        return 3.14 * self._radius ** 2

c = Circle(3)
print(c.area)  # 28.26
# c.area = 50  # ❌ Error: can't set attribute

4. Inherit from another class

class Animal:
    def speak(self):
        return "Some sound"

class Dog(Animal):
    def speak(self):
        return "Bark"

d = Dog()
print(d.speak())  # Bark

5. Override a method

class Animal:
    def speak(self):
        return "Some sound"

class Cat(Animal):
    def speak(self):
        return "Meow"

c = Cat()
print(c.speak())  # Meow

6. Use super() to call base class method

class Animal:
    def speak(self):
        return "Some sound"

class Dog(Animal):
    def speak(self):
        base = super().speak()
        return base + " + Bark"

d = Dog()
print(d.speak())  # Some sound + Bark

7. Use __repr__() or __str__()

class Dog:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f"Dog('{self.name}')"

    def __str__(self):
        return f"My dog's name is {self.name}"

d = Dog("Buddy")
print(repr(d))  # Dog('Buddy')
print(str(d))   # My dog's name is Buddy

Absolutely! Here's the full ChatGPT response on polymorphism, polished and formatted so you can save it, review it, or turn it into a markdown or flashcard:


🧱 What is Polymorphism in Python?

🔁 Definition:

Polymorphism means "many forms" — the same function or method behaves differently depending on the object it’s acting on.


💡 Real-World Analogy:


🧪 Python Polymorphism Example 1: Method Overriding

This is classic runtime polymorphism through inheritance:

class Animal:
    def speak(self):
        return "Some sound"

class Dog(Animal):
    def speak(self):
        return "Bark"

class Cat(Animal):
    def speak(self):
        return "Meow"

animals = [Dog(), Cat()]

for animal in animals:
    print(animal.speak())  # Bark, Meow

✅ You call the same method (speak()), but each class handles it differently.


🦆 Python Polymorphism Example 2: Duck Typing

Python doesn’t require a shared parent class — it just cares if the object has the right method.

class Bird:
    def fly(self):
        print("Flapping wings")

class Plane:
    def fly(self):
        print("Engines on")

def lift_off(flier):
    flier.fly()

lift_off(Bird())   # Flapping wings
lift_off(Plane())  # Engines on

✅ As long as the object has a .fly() method, it can be passed in — “if it quacks like a duck...”


🧠 TL;DR:

Concept Meaning
Polymorphism Same method name, different behavior
Method override Subclasses implement their own version
Duck typing Type doesn't matter, behavior does
Benefit Cleaner, extensible, decoupled code

Would you like me to export this explanation as a .md, .txt, or add it to a reference doc for your interview prep?

Data Types

Absolutely — knowing your core data types inside and out is essential for LeetCode and coding interviews. These are the types you’ll see constantly and will use to build efficient solutions.

Here’s a curated list of the must-know data types for LeetCode — including how to use them, when to choose them, and a one-liner to remember what they’re best at.


🧠 LeetCode Data Types You Should Know (Python)


1. int – Whole numbers

Used for counting, math, binary, etc.

n = 42

🧪 Use cases:


2. float – Decimal numbers

Used rarely, but important for precision-sensitive problems.

pi = 3.14

🧪 Watch out for rounding errors.


3. str – Strings

🔥 High-frequency on LeetCode

s = "leetcode"

🧪 Know:


4. list – Ordered, mutable collection

🔥 Most used structure in LeetCode

arr = [1, 2, 3]

🧪 Know:


5. tuple – Ordered, immutable collection

Used for keys in sets/dicts or returning multiple values.

t = (1, 2)

🧪 Know:


6. set – Unordered, unique items

🔑 Great for fast lookup and duplicates

s = set([1, 2, 3])

🧪 Know:


7. dict – Key-value pairs

🔥 Critical for hash maps / fast lookups

d = {"a": 1, "b": 2}

🧪 Know:


8. collections.deque – Double-ended queue

⚡ Fast append and popleft() → great for BFS

from collections import deque
q = deque([1, 2])
q.append(3)
q.popleft()

9. heapq / Min Heap (via list)

💡 Use for priority queue, top K elements

import heapq
h = [5, 3, 8]
heapq.heapify(h)
heapq.heappop(h)

🧪 Python only has min-heaps — invert values for max-heap.


10. collections.Counter – Fast frequency counting

from collections import Counter
c = Counter("aabbcc")

🧪 Useful for:


🧠 TL;DR: Memorize These for LeetCode

Type What it's good for
int Counting, math
float Precision, rarely needed
str Manipulation, parsing, search
list Arrays, stacks, sliding window
tuple Hashable keys, return multiple items
set Uniqueness, fast lookup
dict Key-value, counting, hash maps
deque BFS, queue (O(1) pops)
heapq Priority queue, top K problems
Counter Fast frequency counting

Would you like: