<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Valorum]]></title><description><![CDATA[Data, models, and methods for all]]></description><link>https://blog.valorumdata.com/</link><image><url>https://blog.valorumdata.com/favicon.png</url><title>Valorum</title><link>https://blog.valorumdata.com/</link></image><generator>Ghost 5.68</generator><lastBuildDate>Mon, 06 Apr 2026 11:10:40 GMT</lastBuildDate><atom:link href="https://blog.valorumdata.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Linked-lists, pattern matching, and recursion in Elixir]]></title><description><![CDATA[Deep dive into the livebook source code to understand pattern matching, recursion, and working with linked lists in Elixir.]]></description><link>https://blog.valorumdata.com/linked-lists-pattern-matching-and-recursion-in-elixir/</link><guid isPermaLink="false">6539a4c762d00d000114ec7f</guid><category><![CDATA[elixir]]></category><category><![CDATA[functional programming]]></category><dc:creator><![CDATA[Spencer Lyon]]></dc:creator><pubDate>Thu, 26 Oct 2023 00:07:31 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1448454050639-2f8d4bf26975?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fHNwaXJhbCUyNTIwcGF0dGVybnxlbnwwfHx8fDE2OTgyNzY1OTV8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1448454050639-2f8d4bf26975?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fHNwaXJhbCUyNTIwcGF0dGVybnxlbnwwfHx8fDE2OTgyNzY1OTV8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Linked-lists, pattern matching, and recursion in Elixir"><p>For <a href="https://blog.valorumdata.com/introducing-jupyteach/" rel="noreferrer">Jupyteach</a> development I have been studying the excellent <a href="https://livebook.dev/?ref=blog.valorumdata.com" rel="noreferrer">Livebook</a> project&apos;s source code. As I am somewhat new to Elixir development, I have been learning a great deal from the pros. Here&apos;s what I learned today...</p><h2 id="linked-lists">Linked Lists</h2><p>In Elixir a list (<code>[a, b, c]</code>) is implemented as a linked list. One implication of the linked-list structure is that prepend operations are O(1), but append or insert operations are O(n).</p><p>To encourage developers to work efficiently with this data structure, Elixir&apos;s pattern matching supports some special syntax exists that makes it easy to take the head of a list (first element) and the rest of the list like so <code>[x | rest]</code>. In this example <code>x</code> will be the first item of the list and <code>rest</code> will be a list with everything else. </p><p>It is also very convenient to prepend a single element to the front of a list by doing  <code>new_list = [x | old_list]</code>, which will be an efficient O(1) operation.</p><h2 id="livebook-notebooks">Livebook Notebooks</h2><p>In livebook&apos;s source code a notebook struct organizes sections and cells as follows: <code>notebook = %{sections: [%{cells: []}]}</code>. </p><p>That is, a <a href="https://github.com/livebook-dev/livebook/blob/e7a92b4c14ec25344d86edf13180ce52c673f1f7/lib/livebook/notebook.ex?ref=blog.valorumdata.com#L38" rel="noreferrer">notebook has a list of sections,</a> each of which has a <a href="https://github.com/livebook-dev/livebook/blob/e7a92b4c14ec25344d86edf13180ce52c673f1f7/lib/livebook/notebook/section.ex?ref=blog.valorumdata.com#L21" rel="noreferrer">list of cells</a>. </p><p>In livebook, you are allowed to move cells up and down by a given offset. This offset might cause the cell to cross section boundaries. The function <code>move_cell/3</code> is responsible for handling this operation. Here&apos;s the code:</p><pre><code class="language-elixir">def move_cell(notebook, cell_id, offset) do
  # We firstly create a flat list of cells interspersed with `:separator`
  # at section boundaries. Then we move the given cell by the given offset.
  # Finally we split the flat list back into cell lists
  # and put them in the corresponding sections.

  separated_cells =
    notebook.sections
    |&gt; Enum.map_intersperse(:separator, &amp; &amp;1.cells)
    |&gt; List.flatten()

  idx =
    Enum.find_index(separated_cells, fn
      :separator -&gt; false
      cell -&gt; cell.id == cell_id
    end)

  new_idx = (idx + offset) |&gt; clamp_index(separated_cells)

  {cell, separated_cells} = List.pop_at(separated_cells, idx)
  separated_cells = List.insert_at(separated_cells, new_idx, cell)

  cell_groups = group_cells(separated_cells)

  sections =
    notebook.sections
    |&gt; Enum.zip(cell_groups)
    |&gt; Enum.map(fn {section, cells} -&gt; %{section | cells: cells} end)

  %{notebook | sections: sections}
end
</code></pre><p>Comments:</p><ul><li><code>separated_cells</code> is a flat list of cells, where in between each section&apos;s cells is the atom <code>:separator</code>. It looks like <code>[cell1, cell2, :separator, cell3, cell4, cell5, ..] </code> where cells 1 and 2 are in the first section and cells 3 to 5 are in the second section.</li><li><code>idx</code> is the original index of the cell we want to move (found using <code>cell_id</code>)</li><li><code>new_idx</code> is the new index where we would like the cell to end</li><li><code>List.pop_at</code> and <code>List.insert_at</code> are used to remove the cell from <code>idx</code> and put it back in at <code>new_idx</code></li><li><code>cell_groups</code> will return <code>list(list(Cell.t()))</code>, for the cells that belong to each section</li><li>Finally the last two chunks of code update the list of cells in each section and then the list of sections in the notebook</li></ul><h2 id="regrouping-cells">Regrouping cells</h2><p>The part I want to focus on is <code>group_cells/1</code>. The implementation is a master class in pattern matching and efficient list operations in Elixir. Here&apos;s the code</p><pre><code class="language-elixir">defp group_cells(separated_cells) do
	separated_cells
	|&gt; Enum.reverse()
	|&gt; do_group_cells([])
end

defp do_group_cells([], groups), do: groups

defp do_group_cells([:separator | separated_cells], []) do
	do_group_cells(separated_cells, [[], []])
end

defp do_group_cells([:separator | separated_cells], groups) do
	do_group_cells(separated_cells, [[] | groups])
end

defp do_group_cells([cell | separated_cells], []) do
	do_group_cells(separated_cells, [[cell]])
end

defp do_group_cells([cell | separated_cells], [group | groups]) do
	do_group_cells(separated_cells, [[cell | group] | groups])
end
</code></pre><p>We enter with <code>group_cells</code> and pass in <code>separated_cells</code>, which is the re-ordered <code>list(Cell.t() | :separator)</code>.</p><p>The code then <em>reverses that list</em> and begins a series of recursive calls into the <code>do_group_cells/2</code> function. In all clauses of this function the first argument is a flat list of cells and the second argument is a list of lists of cells. The outer list is for sections. Each inner list is a group of cells in that section.</p><p>We begin our time in <code>do_group_cells/2</code> by passing the reversed <code>separated_cells</code> list as the first argument and an empty list (<code>[]</code>) as the second.</p><blockquote>Note: I originally started this deep dive by trying to figure out why the list of cells was being reversed and how it was ever &quot;un-reversed&quot;.</blockquote><h3 id="recursion-and-pattern-matching">Recursion and Pattern Matching</h3><p>This will match either the 2nd or 4th clause (due to the empty list as the second argument).</p><p>If our reversed list happened to begin with a <code>:separator</code>, we go to the 2nd clause. Here we throw away the separator (by keeping only the tail of the first argument) and then make a recursive call updating the second argument to be <code>[[], []]</code>.</p><p>Why <code>[[], []]</code>? To see we need to follow the recursive call into the 5th clause (why 5th and not 3rd? because we won&apos;t have two <code>:separator</code> atoms in a row).</p><p>The 5th clause is the work horse. It uses pattern matching to split the first argument into head (called <code>cell</code>) and tail (called <code>separated_cells</code>) and splits the second argument into head <code>group</code> (list of cells in current section) and tail <code>groups</code> (the other sections and their cells).  The only line in the body of this function is to make another recursive call to <code>do_group_cells/2</code> passing <code>separated_cells</code> as the first argument and <code>[[cell | group] | groups]</code> as the second. This second argument does two things: (1) puts the single cell at the head of the current group and (2) puts this updated group ahead of existing groups.</p><p>Comments:</p><ul><li>By always peeling <code>cell</code> of the head of the list of cells and then adding it to the front of the current group (updated group to the front of the list of groups), we end up undoing the <code>List.reverse</code> from <code>group_cells/1</code></li><li>By always passing <code>separated_cells</code> as the first argument in the recursive call that list shrinks by one each time until it is empty. When it is empty we fall into the first clause and recursion ends.</li></ul><p>To get here we followed the 2nd clause. Suppose, on the other hand that we end up in the 4th clause to begin the recursion. This happens whenever the reversed list of separated cells does not begin with <code>:separator</code>. In this clause we match the head of our cells to <code>cell</code> and the tail to <code>separated_cells</code>. We then do do a recursive call into <code>do_group_cells/2</code> <code>separated_cells</code> as the first argument and the second argument as <code>[[cell]]</code>. This will match the 5th (or 3rd if the new head of <code>separated_cells</code> is <code>:separator</code>) clause and we go to work as described above!</p><p>The final piece of the puzzle is the 3rd clause. This matches when the current list of reversed cells begins with <code>:separator</code>. Here the recursive call will throw away <code>:separator</code>, pass the tail of the cell list in the first position and then <code>[[] | groups]</code> as the second. This sets up a new empty cell list for the current group and we recurse back into the 5th clause.</p><h2 id="learning-from-the-best">Learning from the best</h2><p><a href="https://en.wikipedia.org/wiki/Functional_programming?ref=blog.valorumdata.com" rel="noreferrer">Functional programming</a> is a powerful approach to modeling and manipulating data. Elixir&apos;s implementation allows for concise and expressive code, but it can seem foreign to someone like me with a stronger background in languages like Python, Julia, Javascript, and Go.</p><p>Thankfully the team behind livebook are experts and have made their code available and open source. It has been exhilarating to study their code and feel like I&apos;m taking a class from the best in class. Open source for the win!</p><h2 id="postscript">Postscript</h2><p>I made use of the <a href="https://about.sourcegraph.com/cody?ref=blog.valorumdata.com" rel="noreferrer">Cody</a> tool from Sourcegraph while I was studying the livebook source code. While not <a href="https://x.com/spencer_lyon/status/1716981798926782895?s=20&amp;ref=blog.valorumdata.com" rel="noreferrer">not perfect</a>, Cody was an excellent study buddy as I dug into this new library.</p>]]></content:encoded></item><item><title><![CDATA[From Raw Data to Refined Insights: How Valorum Data Maximizes Data Utility]]></title><description><![CDATA[<p>Data, like crude oil, holds vast potential but requires refinement for value. Its worth is in the insights gained from analysis, influencing strategic and operational choices. Furthermore, with the integration of machine learning and artificial intelligence, data can be leveraged to predict trends, optimize processes, and make smarter decisions. Data-driven</p>]]></description><link>https://blog.valorumdata.com/data-warehouses-by-valorum/</link><guid isPermaLink="false">65317b8362d00d000114ec05</guid><category><![CDATA[data]]></category><category><![CDATA[python]]></category><category><![CDATA[data enginnering]]></category><category><![CDATA[data warehouse]]></category><dc:creator><![CDATA[Spencer Lyon]]></dc:creator><pubDate>Mon, 23 Oct 2023 12:51:50 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1606340671662-27ee685dd111?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDEyfHxwaXBlc3xlbnwwfHx8fDE2OTc3Njc3MTl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1606340671662-27ee685dd111?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDEyfHxwaXBlc3xlbnwwfHx8fDE2OTc3Njc3MTl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="From Raw Data to Refined Insights: How Valorum Data Maximizes Data Utility"><p>Data, like crude oil, holds vast potential but requires refinement for value. Its worth is in the insights gained from analysis, influencing strategic and operational choices. Furthermore, with the integration of machine learning and artificial intelligence, data can be leveraged to predict trends, optimize processes, and make smarter decisions. Data-driven organizations, bolstered by these technologies, are more successful, innovative, and prepared for the future. However, before harnessing this potential, the challenge of data storage and access must be addressed, which is the primary focus of this blog post.</p><p>In today&apos;s interconnected world, modern companies face the intricate challenge of integrating seamlessly with a myriad of external applications, including marketing tools like <a href="https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=&amp;cad=rja&amp;uact=8&amp;ved=2ahUKEwjKsu7XpYWCAxVUmYQIHd5ODMkQFnoECAcQAQ&amp;url=https%3A%2F%2Fmailchimp.com%2F&amp;usg=AOvVaw3Q80b2VwzXDpklMABnKxc6&amp;opi=89978449" rel="noreferrer">Mailchimp</a>, payment providers like <a href="https://stripe.com/?ref=blog.valorumdata.com" rel="noreferrer">Stripe</a>, and CRM systems like <a href="https://www.salesforce.com/?ref=blog.valorumdata.com" rel="noreferrer">Salesforce</a>. Traditional business infrastructures often falter when interfacing with these diverse platforms, lacking in efficiency and cost-effectiveness. Recognizing this gap, the team at Valorum Data specializes in advanced integration strategies. Our latest endeavors are geared towards crafting bespoke solutions tailored to specific organizations and projects, ensuring they can smoothly interact with these vital external systems and achieve transformative outcomes.</p><h2 id="building-customized-data-warehouses">Building Customized Data Warehouses</h2><p>When it comes to assembling the perfect data warehouse, one size does not fit all. In the past few decades, we as an industry have learned a few strategies for effectively managing and maintaining a data warehouse. On such pattern is the  Extract, Load, Transform (ELT) strategy &#x2013; a variant of the traditional Extract, Transform, Load (ETL) process . At Valorum, we create ELT pipelines that <strong>extract</strong> data from a variety of sources/APIs/databases/external applications, <strong>load</strong> all data into a data warehouse, and then <strong>transform</strong> the data within the warehouse. This powerful paradigm is deployed at many of the leading  data-first firms today. However, the majority of companies do not operate at a large enough scale to justify having an in-house data engineering team. This is why Valorum Data has been building custom data warehouses for clients, tailoring each one to suit the unique needs of the organization.</p><p>A crucial part of any data warehouse is the choice of where to store the data. We utilize different systems such as <a href="https://www.timescale.com/?ref=blog.valorumdata.com" rel="noreferrer">TimescaleDB,</a> <a href="https://www.snowflake.com/en/?ref=blog.valorumdata.com" rel="noreferrer">Snowflake</a>, and <a href="https://cloud.google.com/bigquery?ref=blog.valorumdata.com" rel="noreferrer">BigQuery</a>, depending upon the volume, variety, and velocity of the data to be managed. These technologies have been designed with scalability at their core, making them instrumental in managing complex business data and supporting advanced analytics.</p><h2 id="streamlining-data-sync-and-transformation">Streamlining Data Sync and Transformation</h2><p>After the data warehouse is set, seamless data integration is paramount. To achieve this, we use <a href="https://airbyte.com/?ref=blog.valorumdata.com" rel="noreferrer">Airbyte</a>, an open-source data integration platform, to sync data from APIs, customer databases and other systems. Furthermore, Valorum has leveraged its expertise to write custom Airbyte connectors for improved accessibility and smoother data integration.</p><p>Data transformations are crucial in a data warehouse to enable effective decision support. For this, we use <a href="https://www.getdbt.com/?ref=blog.valorumdata.com" rel="noreferrer">dbt</a> (data build tool), which allows us to perform transformations within the warehouse post extraction and loading. The power of dbt lies in its ability to manage complex transformations and enable version control, all while maintaining transparency through automatic documentation. By converting raw data into a more suitable form for reporting and analytics, dbt takes data from accessible to actionable.</p><h2 id="creating-custom-applications-and-reports">Creating Custom Applications and Reports</h2><p>The end goal of all these processes is to generate actionable insights. To that end, we build custom applications and automated reports on top of the data warehouse. Leveraging a variety of Python tools, we can present the data in the most effective and easily digestible format: as dashboards, interactive visualizations, automated reports, and more. These tools give businesses the power to actively make use of their data in real-time, making them more dynamic and responsive.</p><p>With the clear, accessible data at our disposal, we work with businesses to utilize an array of machine learning and artificial intelligence algorithms to delve deeper into the data. Whether you want to predict future trends, identify anomalies, or segment your customer base, our data infrastructure creates the optimum environment for these predictive analytics. Machine learning and AI thrive on big, clean data, and that&apos;s precisely what we provide, thus allowing organizations to make the leap from data-driven to AI-driven. This ushers in the next level of intelligent decision-making, proactively leveraging data to gain a competitive edge.</p><h2 id="join-the-fun">Join the Fun</h2><p>In conclusion, every organization&apos;s data is a treasure trove of insights waiting to be unearthed. However, unlocking the full potential of this data can be challenging without the right strategy and tools. With an organized approach to data storage and access, Valorum Data is helping organizations build the necessary infrastructure to become data-driven.</p><p>As we continue expanding and refining our strategies, we invite you to be part of our journey. If you&apos;re interested in learning more about our work or discussing how we can support your organization&apos;s data needs, please reach out to the Valorum team for a consulting engagement. Whether you are just starting a data strategy or well on your way, we can help you reach your goals. Alternatively, subscribe to our newsletter to stay up-to-date with our latest advancements, and have useful data insights delivered straight to your mailbox. </p><p>At Valorum Data, we don&apos;t just provide services, we equip you with the power to transform your data into a potent strategic advantage. Regardless of the complexity of your data landscape, we can help you navigate through it, unlocking significant value along the way. Harness the power of your data with Valorum Data, and make your organization truly data-driven.</p>]]></content:encoded></item><item><title><![CDATA[Introducing Jupyteach]]></title><description><![CDATA[Introducing Jupyteach, a new LMS for learning and teaching Data with Python]]></description><link>https://blog.valorumdata.com/introducing-jupyteach/</link><guid isPermaLink="false">652957aa62d00d000114eb8b</guid><category><![CDATA[jupyteach]]></category><category><![CDATA[elixir]]></category><category><![CDATA[python]]></category><dc:creator><![CDATA[Spencer Lyon]]></dc:creator><pubDate>Thu, 19 Oct 2023 18:58:48 GMT</pubDate><media:content url="https://blog.valorumdata.com/content/images/2025/04/logo_dark.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.valorumdata.com/content/images/2025/04/logo_dark.svg" alt="Introducing Jupyteach"><p>The Valorum team has a passion for learning and teaching. We love to explore new ideas and help others feel the energy that comes from gaining knowledge. Over the past 10 years we have continuously taught courses at a number of universities around the world. Our courses are mostly Python based (some Julia) and cover topics at the frontier of economics, machine learning, and data science. During our experience, we have searched for the best way to teach in person and remote courses on these topics. </p><p>We&apos;ve tried everything.</p><p>We mean everything... </p><ul><li>traditional learning management systems (LMS) including <a href="https://www.instructure.com/canvas?ref=blog.valorumdata.com" rel="noreferrer">Canvas</a>, <a href="https://moodle.org/?ref=blog.valorumdata.com" rel="noreferrer">Moodle</a>, <a href="https://edu.google.com/intl/ALL_us/workspace-for-education/classroom/?ref=blog.valorumdata.com" rel="noreferrer">Google Classroom</a>, and <a href="https://www.d2l.com/?ref=blog.valorumdata.com" rel="noreferrer">Brightspace</a></li><li>developer tools like <a href="https://github.com/?ref=blog.valorumdata.com" rel="noreferrer">GitHub</a> and <a href="https://docs.github.com/en/education/manage-coursework-with-github-classroom/get-started-with-github-classroom/about-github-classroom?ref=blog.valorumdata.com" rel="noreferrer">GitHub Classrooms</a></li><li>data science specific platforms like <a href="https://cocalc.com/?ref=blog.valorumdata.com" rel="noreferrer">Cocalc</a> and <a href="https://jupyter.org/hub?ref=blog.valorumdata.com" rel="noreferrer">Jupyterhub</a>. </li></ul><p>Each of these tools is excellent in many ways, but none of them was quite right for the way we like to teach courses. We build all our lecture notes in Jupyter notebooks. We like to mix explanation -&gt; example -&gt; exercises/practice freely in the notes themselves. We encourage students to alter the codes and explore different options and possibilities. We often <a href="https://en.wikipedia.org/wiki/Flipped_classroom?ref=blog.valorumdata.com" rel="noreferrer">flip the classroom</a>, so great video support is a must.</p><p>So, we decided to create Jupyteach. A new LMS, streamlined for our needs. It doesn&apos;t do most of the things some of these other platforms do. But what it misses in terms of features it makes up for in ease of use and powerful interactivity. </p><p>Jupyteach is under active development (and use at multiple universities including New York University and Peking University HSBC Business School) and is in the alpha stage. In this post we will give an outline of our current progress as well as hint at future plans and ideas. We will provide updates in future posts.</p><h2 id="features">Features</h2><p>We are excited about Jupyteach, primarily because it does exactly what we need it to. No more, no less. The key features already implemented in Jupyteach include the following:</p><ul><li>User management: users can sign up via email+password or via email and passwordless codes sent to their inbox</li><li>Course management: users that are instructors can create courses. Within a course instructors can invite students other instructors and TAs, upload a syllabus, and manage course content (see below)</li><li>Communication: <ul><li>Announcements: instructors can create announcements that appear on the announcements page of their course and are also delivered to all students via email</li><li>Discussions: all course participants can start a discussion thread </li></ul></li><li>Content: content on Jupyteach is organized in a two-level hierarchy. The smallest unit of content is a content block. Content blocks can be organized into lectures. Content blocks can be one of a few different types<ul><li>Notebook: a Jupyter notebook that will be rendered in a live computational environment powered entirely by the user&apos;s browser using the <a href="https://jupyterlite.readthedocs.io/en/stable/?ref=blog.valorumdata.com" rel="noreferrer">JupyterLite</a> project. This means (1) no installation step for students (2) no server management for instructors and (3) interactive lecture notes!</li><li>Video: an embedded video hosted either on YouTube or Vimeo</li><li>Markdown: a standalone markdown document that is rendered on its own page</li><li>Assignment upload: A place for students to attach/upload Jupyter notebooks they have completed as homework</li><li>Link: a link to an external resource such as a data file or pdf</li><li>Quiz: an interactive, auto-graded quiz  (see below)</li></ul></li><li>Quizzes: automatic grading is a must for our teaching. We like to give students many opportunities to practice the concepts they are taught, but doing so typically comes at the cost of more time spent grading assignments. So, Jupyteach has quiz functionality. Quizzes are composed of multiple questions, all of which are automatically graded as the student submit responses. Questions can be of multiple types:<ul><li>Single selection: a user is presented with a prompt and a list of options. They must select the single correct option</li><li>Multiple selection: a user is given a prompt and a list of options. They must select all correct options</li><li>Code: the user is given a description of a programming task and some starter code. They must modify the code so it correctly solves the task. Correctness is verified by running the user&apos;s against a test suite set up by the instructor. The Python test code is run in the student&apos;s browser, making the automated quiz system cheap, efficient, and scalable.</li><li>Fill in the blank: the user is given a problem description and a piece of code that has missing values. They must fill in the missing values. Correctness is verified using a test suite using the filled-in code similar to the Code questions</li></ul></li></ul><h2 id="real-time">Real Time</h2><p>One unique aspect of Jupyteach is the technology we chose to build on. We are using the <a href="https://www.phoenixframework.org/?ref=blog.valorumdata.com" rel="noreferrer">Phoenix web framework</a> &#x2013; a powerful web framework for the <a href="https://elixir-lang.org/?ref=blog.valorumdata.com" rel="noreferrer">Elixir</a> programming language. Elixir is built on top of <a href="https://www.erlang.org/?ref=blog.valorumdata.com" rel="noreferrer">Erlang/OTP</a> and the associated <a href="https://www.erlang.org/blog/a-brief-beam-primer/?ref=blog.valorumdata.com" rel="noreferrer">BEAM</a> virtual machine. The BEAM is known for being extremely resilient and scalable. What this means for Jupyteach is that we will be able to build real time features (think google docs) with shockingly little effort.</p><p>We have big ideas and plans for this, but none of them are quite ready to talk about yet. As soon as we finalize the core feature set (9 of 11 items done), we plan to shift engineering efforts to real time system. Keep an eye on this space!</p><h2 id="looking-forward">Looking Forward</h2><p>We have many excited things planned for Jupyteach and can&apos;t wait to share them with you. We&apos;ll be posting here regularly, so subscribe today to stay up to date!</p>]]></content:encoded></item><item><title><![CDATA[Hello world]]></title><description><![CDATA[<hr><h2 id="welcome">Welcome</h2><p>Greetings to the curious, the learners, and the experts! We&apos;re thrilled to have you join us on this exciting journey of exploration into the ever-evolving world of data. If you have an insatiable appetite for the technical intricacies of data science, machine learning, data engineering, programming, economics,</p>]]></description><link>https://blog.valorumdata.com/hello-world/</link><guid isPermaLink="false">65273ead11996f000146fc21</guid><category><![CDATA[General]]></category><dc:creator><![CDATA[Spencer Lyon]]></dc:creator><pubDate>Thu, 12 Oct 2023 00:54:41 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1451187580459-43490279c0fa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHdvcmxkfGVufDB8fHx8MTY5NzA3MDc2OXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<hr><h2 id="welcome">Welcome</h2><img src="https://images.unsplash.com/photo-1451187580459-43490279c0fa?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHdvcmxkfGVufDB8fHx8MTY5NzA3MDc2OXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Hello world"><p>Greetings to the curious, the learners, and the experts! We&apos;re thrilled to have you join us on this exciting journey of exploration into the ever-evolving world of data. If you have an insatiable appetite for the technical intricacies of data science, machine learning, data engineering, programming, economics, and statistics, you&apos;ve landed in the right place.</p><h3 id="who-are-we"><strong>Who Are We?</strong></h3><p>Established in 2018, Valorum Data has carved a niche in the data consulting arena. With hands-on experience in a diverse range of industries&#x2014;including healthcare, power and energy, retail, finance, education, and manufacturing&#x2014;we&apos;ve developed a solid understanding of how to unlock the latent power of data across disciplines. Our core services reflect our dual commitment:</p><ol><li><strong>Training and Coaching</strong>: We believe in empowering individuals and teams, equipping them with the skills and knowledge to navigate the intricate landscape of data.</li><li><strong>Custom Solution Design, Implementation, and Support</strong>: Our expertise isn&#x2019;t limited to guidance. We roll up our sleeves to design, execute, and maintain bespoke data solutions tailored to specific challenges and industry nuances.</li></ol><p>At Valorum, it&apos;s not just about the depth of our knowledge; it&apos;s about the breadth of our experience and the practical solutions we bring to the table.</p><h3 id="whats-in-store-for-you"><strong>What&apos;s in store for you?</strong></h3><p>This blog promises a blend of the technical and the theoretical:</p><ul><li><strong>Code Away</strong>: Dive deep into rich content full of code snippets and practical examples, tailored to help you grasp complex concepts.</li><li><strong>Theory Meets Practice</strong>: As we delve into advanced topics, we&apos;ll ensure a balanced marriage between underlying theories and their real-world applications.</li><li><strong>Interdisciplinary Insights</strong>: The fusion of programming with economics, statistics with machine learning, and so much more, awaits you. Our posts will often crisscross these domains, reflecting the interdisciplinary nature of today&apos;s data challenges.</li></ul><h3 id="why-should-you-join-our-journey"><strong>Why should you join our journey?</strong></h3><p>Because we&apos;re passionate, not just about crunching numbers, but about understanding them, analyzing them, and sharing the knowledge we garner. Every blog post is an opportunity for us to learn alongside you, to question, to discover, and to grow.</p><p>And while the realm of data might sometimes feel overwhelming, remember: every expert was once a beginner. Whether you&apos;re just starting out or have been in the field for years, there&apos;s always something new waiting on the horizon.</p><p>In the bustling world of AI, there&apos;s more than just algorithms and code. It&apos;s about unlocking new avenues for businesses, catalyzing growth, and driving innovation. With us, you&apos;ll not only learn the technicalities of AI but also explore its myriad business applications. From streamlining operations to gaining a competitive edge, delve into the transformative power of AI in reshaping industries and redefining success.</p><h3 id="engage-with-us"><strong>Engage with Us!</strong></h3><p>Dive into the conversation and become an integral part of our community. We value every insight, feedback, and perspective you bring to the table, and we&apos;re eager to hear from you. Whether it&apos;s a topic you&apos;d like us to cover, a comment on a recent post, or a challenging question you&apos;ve encountered, share your thoughts.</p><p>The world of data is ever-evolving, and we want to ensure you&apos;re always in the loop. By subscribing to our newsletter, you get a curated selection of our latest insights, tutorials, and discussions delivered right to your inbox. Stay connected, stay informed.</p><p>Beyond this blog, our proficiency spans a wide spectrum of services. Whether it&apos;s teaching advanced courses, providing one-on-one or team-based coaching, or crafting bespoke development solution; we have the expertise to support your needs. For businesses and individuals alike, our team is geared up to offer tailored assistance, ensuring that you harness the full potential of data. Reach out, and let&apos;s discuss how our diverse offerings can align with your objectives and propel your projects forward.</p><p>To infinite learning and beyond!</p><p>Warm regards</p><p><strong>Valorum Data</strong></p>]]></content:encoded></item></channel></rss>