Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download
Views: 924
#1.7.3: Good #1.7.4: There are two problems. #(1) The insertion is not in the correct place if the consecutive elements are given in the wrong order. #(2) You haven't taken into account the idea of "cyclically consecutive." I'll explain that in class. # - These should be fixed! #1.8.1: It works well, though it would be nice if it gave an error message if $a > b$. # - fixed! import math import random import functools # ''' # ---====================--- # Begin Helper Methods # ---====================--- # ''' def merge(arr, l, m, r, cmp, reverse): cmp_helper = cmp if reverse: cmp_helper = lambda a, b: not cmp(a, b) left_midpoint = m - l + 1 right_midpoint = r - m temp_arr_left = [arr[l + i] for i in range(left_midpoint)] temp_arr_right = [arr[m + 1 + i] for i in range(right_midpoint)] i = 0 j = 0 k = l while i < left_midpoint and j < right_midpoint: if cmp_helper(temp_arr_left[i], temp_arr_right[j]): arr[k] = temp_arr_left[i] i += 1 else: arr[k] = temp_arr_right[j] j += 1 k += 1 while i < left_midpoint: arr[k] = temp_arr_left[i] i += 1 k += 1 while j < right_midpoint: arr[k] = temp_arr_right[j] j += 1 k += 1 def merge_sort(arr, left_index=None, right_index=None, cmp=lambda a, b: a < b, reverse=False): if left_index is None: left_index = 0 if right_index is None: right_index = len(arr) - 1 if left_index < right_index: midpoint = math.floor((left_index + right_index - 1)/2) merge_sort(arr, left_index, midpoint, cmp, reverse) merge_sort(arr, midpoint + 1, right_index, cmp, reverse) merge(arr, left_index, midpoint, right_index, cmp, reverse) def css_classes(): ''' pseudo-css-class generator!! dictionary mapping { pseudo-classname: inline-style } ''' classes = { 'border-light': 'border: 1px solid #a0aec0;', 'text-light': 'color: #e6fffa;', 'text-dark': 'color: #cbd5e0;', 'rounded': 'border-radius: 3px;', 'bg-dark': 'background-color: #1a202c;', 'w-max': 'width: max-content;', 'flex': 'display: flex;', 'block': 'display: block;', 'justify-between': 'justify-content: space-between;', 'text-center': 'text-align: center;', } spacings = range(0, 12) scale_factor = 1.6 # note, cocalc uses rootFontSize=10px, I want to pretend it's 16px scale_rem = lambda x: str(round(x * scale_factor, 3)) text_prefixes = 'xs sm base lg xl 2xl 3xl 4xl 5xl 6xl'.split() text_rem_sizes = [0.75, 0.875, 1, 1.125, 1.25, 1.5, 1.875, 2.25, 3, 4] classes.update({'text-{}'.format(text_prefixes[i]): 'font-size: {}rem;'.format(scale_rem(text_rem_sizes[i])) for i in range(len(text_prefixes))}) spacing_opts = { 'l': ['left: '], 'r': ['right: '], 't': ['top: '], 'b': ['bottom: '] } spacing_opts.update({ 'x': spacing_opts['l'] + spacing_opts['r'], 'y': spacing_opts['t'] + spacing_opts['b'] }) spacing_opts[''] = spacing_opts['x'] + spacing_opts['y'] for spacing in spacings: space = str(round(spacing * 0.25, 2)) + 'rem; ' for variant in ["margin", "padding"]: for prefix, rule_list in spacing_opts.items(): classes[variant[0] + prefix + '-' + str(spacing)] = "".join([variant + "-" + rule + space for rule in rule_list]) return classes def apply_classes(raw_html, classes=None): ''' pseudo-css-class injector!! note, doesn't actually support bem cause Im not caring about uniqueness (ie. card__header can be affected by card) params: - raw_html: string containing html!! - classes: object mapping classes to further either standard class names or inline styles (simulates @apply behavior from tw) ''' if classes is not None: for k, v in classes.items(): raw_html = raw_html.replace(k, v) rules = css_classes() for rule, definition in rules.items(): raw_html = raw_html.replace(rule, definition) return raw_html def assignment_html(exernum, assignment, funcs=None, params=None): ''' returns html for the assignment definition! func=[{ 'name': 'listswitch(lis, i, k)', 'params': ['lis: some list', 'i: index', 'k: index'], 'returns': ['lis with indices i and k switched'] }], params: - exernum: number of the exercise - assignment: problem statement - func: optional list of dictionaries describing functions. needs the following key-value pairs - name: <string> - params: <list<string>> - returns: <list<string>> - params: optional list of interactive inputs ''' res = ''' <div style="margin: 4rem 0;"> <h1>Exercise {}</h1> <p><b>Assignment:</b> {}</p> '''.format(exernum, assignment) if funcs: for func in funcs: res += '<p><b>Function:</b><code style="block mt-4 ml-4">{}</code></p>'.format(func.get('name', '')) if 'params' in func: res += '<div style="ml-4"><i>params:</i><ul>' for param in func['params']: res += "<li>{}</li>".format(param) res += "</ul></div>" if 'returns' in func: res += '<div style="ml-4"><i>returns:</i><ul>' for param in func['returns']: res += "<li>{}</li>".format(param) res += "</ul></div>" if params: res += "<p><b>Interactive input:</b></p><ul>" for param in params: res += "<li>{}</li>".format(param) res += "</ul>" res += '</div>' return apply_classes(res) def plot_arr(arr): ''' helper for show so that we can pass lists ''' return functools.reduce(lambda a,b : a + b, arr) def show_all(arr): ''' helper for show so that we can pass lists ''' for el in arr: show(el) def dist(point_a, point_b): ''' helper to give distance between two points of equal dimension params: - point_a: tuple for point a - point_b: tuple for point b ''' return sum([(a - b) ** 2 for a, b in zip(point_a, point_b)]) ** 0.5 def all_indices(arr, el): ''' helper to give all indices of an element in an array ''' return [i for i in range(len(arr)) if arr[i] == el] def random_list(length, min_val=0, max_val=20): ''' makes a random list ''' return [random.randint(min_val, max_val) for _ in range(length)] def arr_cmp(arr, cmp=lambda a, b: a < b, reverse=False): ''' min/max helper with comparison function params: - arr: array - amp: comparison function - reverse: order of results returns extreme of arr according to cmp ''' cmp_helper = cmp if reverse: cmp_helper = lambda a, b: not cmp(a, b) if len(arr) == 0: return None # maybe should raise an exception, not sure res = arr[0] for el in arr: if cmp_helper(el, res): res = el return res def assignment(definition, func): ''' assignment runner ''' definition() interact(func) class inputs: def __init__(self): pass @staticmethod def num(num=None, label='number', min_val=-10, max_val=10): if not num: num = random.randint(min_val, max_val) return input_box(default=num, label=label) @staticmethod def arr(num=None, label='arr', min_val=-10, max_val=10): if not num: num = random.randint(3, 10) return input_box(default=str(random_list(num, min_val, max_val)), label=label) @staticmethod def switch(val=False, label='show'): return (label, val) # ''' # ---========================--- # End Helper Methods # -------- # Begin Assignment Defs # ---========================--- # ''' assignment_defs = { '1.7.3': lambda: html(assignment_html( '1.7.3', 'Make a function that takes a list and two indices and switches the elements of the list corresponding to those indices.', funcs=[{ 'name': 'listswitch(lis, i, k)', 'params': ['lis: some list', 'i: index', 'k: index'], 'returns': ['lis with indices i and k switched'] }], params=[ '(a) A list, denoted lis.', '(b) The first index, denoted i.', '(c) The second index, denoted k.', '(d) A switch to show or not show the switched list; the default is not to show the switched list.' ] )), '1.7.4': lambda: html(assignment_html( '1.7.4', 'Make a function that takes a list with distinct elements, two cyclically consecutive elements of the list (in either order) and an arbitrary element, and inserts the arbitrary element into the list between the two consecutive elements.', funcs=[{ 'name': 'list_insert_between(lis, lis_elt_one, lis_elt_two, any_elt)', 'params': [ 'lis: some list', 'lis_elt_one: an element of the list', 'lis_elt_two: another element of the list (must be directly before or after lis_elt_one)', 'any_elt: an arbitrary element to be inserted', ], 'returns': ['lis with indices i and k switched'] }], params=[ '(a) A list, denoted lis.', '(b) An element of the list, denoted lis_elt_one.', '(c) Another element of the list, denoted lis_elt_two.', '(d) An arbitrary element, denoted any_elt.', '(e) A switch to show or not show the list with the inserted element; the default is not to show that list.' ] )), '1.8.1': lambda: html(assignment_html( '1.8.1', 'Take two numbers a and b, and use a for loop to write all numbers a<sup>2</sup>, (a + 1)<sup>2</sup>,...,b<sup>2</sup>.', params=['(a) First number, denoted a.', '(b) Second number, denoted b.',] )) } # ''' # ---========================--- # End Assignment Defs # -------- # Begin Assignment Methods # ---========================--- # ''' def swap(arr, i, j): ''' swaps indices i and j in an array! ignores out of bound indices ''' arr = list(arr) if all([index in range(len(arr)) for index in [i, j]]): tmp = arr[j] arr[j] = arr[i] arr[i] = tmp return arr def insert_between(arr, el_one, el_two, to_insert): # if el_one or el_two not in arr, return None if not all([el in arr for el in [el_one, el_two]]): return None # get all occurences of el_one and el_two el_one_indices = all_indices(arr, el_one) el_two_indices = all_indices(arr, el_two) inserted = list(arr[:]) if arr[-1] == el_one and arr[0] == el_two: inserted.insert(0, to_insert) return inserted if arr[0] == el_one and arr[-1] == el_two: inserted.insert(0, to_insert) return inserted # insert between consecutive indices if any exist for i in el_one_indices: if i+1 in el_two_indices: inserted.insert(i+1, to_insert) break if i-1 in el_two_indices: inserted.insert(i, to_insert) break return inserted square_all_between = lambda a, b: ['a = {}'.format(a), 'b = {}'.format(b)] + [n ** 2 for n in range(a, b+1)] # ''' # ---==========================--- # End Assignment Methods # -------- # Begin Interactive Methods # ---==========================--- # ''' def interact_switch_indices( lis=inputs.arr(label='List'), i=inputs.num(min_val=0, max_val=7, label='First index'), k=inputs.num(min_val=0, max_val=7, label='Second index'), show_list=inputs.switch(label='Show switched list'), ): res = [ "List: {}".format(lis), "i: {}".format(i), "k: {}".format(k), ] if show_list: res += ["Switched List: {}".format(swap(lis, i, k))] show_all(res) def interact_insert_between( lis=inputs.arr(num=8, label='List'), lis_elt_one=inputs.num(num=3, label='First elem'), lis_elt_two=inputs.num(num=4, label='Second elem'), any_elt=inputs.num(num=5, label='To insert'), show_list=inputs.switch(label='Show original list'), ): inserted = insert_between(lis, lis_elt_one, lis_elt_two, any_elt) if inserted is None: return html(apply_classes('<p style="text-center"><b>Not all elements in the list</b></p>')) res = [ "List: {}".format(lis), "First Elem: {}".format(lis_elt_one), "Second Elem: {}".format(lis_elt_two), "To Insert: {}".format(any_elt), "Valid Elements?: {}".format(len(inserted) > len(lis)), ] if show_list: res += ["Switched List: {}".format(inserted)] show_all(res) def interact_square_all_between(a=inputs.num(num=3, label='a'), b=inputs.num(num=10, label='b')): if a > b: show("error, a cannot be greater than b") else: show_all(square_all_between(a, b)) interactive = { '1.7.3': interact_switch_indices, '1.7.4': interact_insert_between, '1.8.1': interact_square_all_between } def run_interactive(run=interactive): for exernum, func in run.items(): assignment(assignment_defs[exernum], func) # ''' # ---=======================--- # End Interactive Methods # --------- # Begin Main # ---=======================--- # ''' def main(): run_interactive() main()

Exercise 1.7.4

Assignment: Make a function that takes a list with distinct elements, two cyclically consecutive elements of the list (in either order) and an arbitrary element, and inserts the arbitrary element into the list between the two consecutive elements.

Function:list_insert_between(lis, lis_elt_one, lis_elt_two, any_elt)

params:
  • lis: some list
  • lis_elt_one: an element of the list
  • lis_elt_two: another element of the list (must be directly before or after lis_elt_one)
  • any_elt: an arbitrary element to be inserted
returns:
  • lis with indices i and k switched

Interactive input:

  • (a) A list, denoted lis.
  • (b) An element of the list, denoted lis_elt_one.
  • (c) Another element of the list, denoted lis_elt_two.
  • (d) An arbitrary element, denoted any_elt.
  • (e) A switch to show or not show the list with the inserted element; the default is not to show that list.
Interact: please open in CoCalc

Exercise 1.7.3

Assignment: Make a function that takes a list and two indices and switches the elements of the list corresponding to those indices.

Function:listswitch(lis, i, k)

params:
  • lis: some list
  • i: index
  • k: index
returns:
  • lis with indices i and k switched

Interactive input:

  • (a) A list, denoted lis.
  • (b) The first index, denoted i.
  • (c) The second index, denoted k.
  • (d) A switch to show or not show the switched list; the default is not to show the switched list.
Interact: please open in CoCalc

Exercise 1.8.1

Assignment: Take two numbers a and b, and use a for loop to write all numbers a2, (a + 1)2,...,b2.

Interactive input:

  • (a) First number, denoted a.
  • (b) Second number, denoted b.
Interact: please open in CoCalc
=