Run this cell first!
%config InteractiveShell.ast_node_interactivity="none"
def f(globals, locals):
import base64
CODE = ("ZGVmIG1ha2VfcHJpbnRfbG9jYWxzKCk6IAogICAgIyBJbiBhIGZ1bmN0aW9uIHRvIHByZXZlbnQgbG9jYWxzIGFuZCBpbXBvcnRzIGZyb20gbGVha2luZy4KICAgIGdsb2JhbCBtYWtlX3ByaW50X2xvY2FscwogICAgZGVsIG1ha2VfcHJpbnRfbG9jYWxzICAjIE9ubHkgcnVuIHRoaXMgZnVuY3Rpb24gb25jZS4KCiAgICBpbXBvcnQgSVB5dGhvbgogICAgaW1wb3J0IGFzdAogICAgaW1wb3J0IGluc3BlY3QKCiAgICBjbGFzcyBWaXNpdG9yKGFzdC5Ob2RlVmlzaXRvcik6CiAgICAgICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgICAgICBzZWxmLnZhcmlhYmxlcyA9IHNldCgpCiAgICAgICAgZGVmIHZpc2l0X05hbWUoc2VsZiwgbmFtZSk6CiAgICAgICAgICAgIHNlbGYudmFyaWFibGVzLmFkZChuYW1lLmlkKQogICAgICAgICMgVE9ETzogUG9zc2libHkgZGV0ZWN0IHdoZXRoZXIgdmFyaWFibGVzIGFyZSBhc3NpZ25lZCB0by4KCiAgICBBTExPV19UWVBFUyA9IFtpbnQsIGZsb2F0LCBzdHIsIGJvb2wsIGxpc3QsIGRpY3QsIHR1cGxlLCByYW5nZV0KICAgIGRlZiBmaWx0ZXJfdmFyaWFibGVzKHZhcmlhYmxlcywgbG9jYWxzKToKICAgICAgICBmb3IgdiBpbiB2YXJpYWJsZXM6CiAgICAgICAgICAgIGlmIHYgaW4gbG9jYWxzIGFuZCB0eXBlKGxvY2Fsc1t2XSkgaW4gQUxMT1dfVFlQRVM6CiAgICAgICAgICAgICAgICB5aWVsZCB2CiAgCiAgICAjIFVuZm9ydHVuYXRlbHksIHRoZXJlIGRvZXNuJ3Qgc2VlbSB0byBiZSBhIHN1cHBvcnRlZCB3YXkgb2YgZ2V0dGluZwogICAgIyB0aGUgY3VycmVudCBjZWxsJ3MgY29kZSB2aWEgdGhlIHB1YmxpYyBJUHl0aG9uIEFQSXMuIEhvd2V2ZXIsIGJlY2F1c2UKICAgICMgd2UgYXJlIGdldHRpbmcgY2FsbGVkIGZyb20gSVB5dGhvbiBpdHNlbGYgYW5kIHdlIGFyZSBhbHJlYWR5IGluc3BlY3RpbmcKICAgICMgdGhlIHN0YWNrdHJhY2UsIHdlIG1pZ2h0IGFzIHdlbGwganVzdCBwZWVrIGludG8gaXRzIGZyYW1lLi4uCiAgICBpZiBJUHl0aG9uLl9fdmVyc2lvbl9fID09ICI1LjUuMCI6CiAgICAgICAgIyBjb2xhYgogICAgICAgIGRlZiBnZXRfYXN0KGZyYW1lKToKICAgICAgICAgICAgcmV0dXJuIGFzdC5Nb2R1bGUoZnJhbWUuZl9iYWNrLmZfYmFjay5mX2xvY2Fsc1sibm9kZWxpc3QiXSkKICAgICAgICBkZWYgZmluZF9sb2NhbHMoZnJhbWUpOgogICAgICAgICAgICByZXR1cm4gZnJhbWUuZl9sb2NhbHMKICAgICAgICBkZWYgYXRfdG9wX2xldmVsKGZyYW1lKToKICAgICAgICAgICAgcmV0dXJuIGZyYW1lLmZfYmFjay5mX2NvZGUuY29fZmlsZW5hbWUuZW5kc3dpdGgoIklQeXRob24vY29yZS9pbnRlcmFjdGl2ZXNoZWxsLnB5IikKCiAgICBlbGlmIElQeXRob24uX192ZXJzaW9uX18gPT0gIjguNC4wIjoKICAgICAgICAjIGxhYiBjb21wdXRlcnMKICAgICAgICBkZWYgZ2V0X2FzdChmcmFtZSk6CiAgICAgICAgICAgIHJldHVybiBhc3QuTW9kdWxlKGZyYW1lLmZfYmFjay5mX2JhY2suZl9sb2NhbHNbIm5vZGVsaXN0Il0pCiAgICAgICAgZGVmIGZpbmRfbG9jYWxzKGZyYW1lKToKICAgICAgICAgICAgcmV0dXJuIGZyYW1lLmZfbG9jYWxzCiAgICAgICAgZGVmIGF0X3RvcF9sZXZlbChmcmFtZSk6CiAgICAgICAgICAgIHJldHVybiBmcmFtZS5mX2JhY2suZl9jb2RlLmNvX2ZpbGVuYW1lLmVuZHN3aXRoKCJJUHl0aG9uL2NvcmUvaW50ZXJhY3RpdmVzaGVsbC5weSIpCiAgICBlbHNlOgogICAgICAgIHByaW50KGYicHJpbnRfbG9jYWxzKCkgbm90IHN1cHBvcnRlZCBvbiBJUHl0aG9uIHZlcnNpb24ge0lQeXRob24uX192ZXJzaW9uX199IikKCiAgICBkZWYgZ2V0X2NlbGxfbmFtZXMoZnJhbWUpOgogICAgICAgIHRyZWUgPSBnZXRfYXN0KGZyYW1lKQogICAgICAgIHZpc2l0b3IgPSBWaXNpdG9yKCkKICAgICAgICB2aXNpdG9yLnZpc2l0KHRyZWUpCiAgICAgICAgcmV0dXJuIGZpbHRlcl92YXJpYWJsZXModmlzaXRvci52YXJpYWJsZXMsIGZyYW1lLmZfbG9jYWxzKQoKICAgIGRlZiBmaW5kX3doaWNoKGZyYW1lKToKICAgICAgICAjIEZyYW1lIGlzIHRoZSBmcmFtZSB3aG9zZSBsb2NhbHMgd2UgYXJlIGludGVyZXN0ZWQgaW4gcHJpbnRpbmcuCiAgICAgICAgaWYgYXRfdG9wX2xldmVsKGZyYW1lKToKICAgICAgICAgICAgIyBUaGUgcGFyZW50IGZyYW1lIG9mIHRoZSBpbnRlcmVzdGVkIGZyYW1lIGlzIGEgbW9kdWxlLCBtb3N0IGxpa2VseQogICAgICAgICAgICAjICJpbnRlcmFjdGl2ZXNoZWxsIi4gVGhpcyBtZWFucyB3ZSBhcmUgaW4gdGhlIGdsb2JhbCBzY29wZSwgc2luY2UKICAgICAgICAgICAgIyBvbmx5IHRoZSBnbG9iYWwgc2NvcGUgc2hvdWxkIGJlIGRpcmVjdGx5IHJ1biBieSB0aGUgaW50ZXJhY3RpdmUgc2hlbGwuCiAgICAgICAgICAgIHJldHVybiBzZXQoZ2V0X2NlbGxfbmFtZXMoZnJhbWUpKQogICAgICAgICMgVGhlIHBhcmVudCBmcmFtZSBpcyBub3QgYSBtb2R1bGUsIHNvIHdlIGFyZSBpbiBhIGxvY2FsIHNjb3BlLgogICAgICAgIHJldHVybiBzZXQoZnJhbWUuZl9sb2NhbHMpCgogICAgZGVmIHByaW50X2xvY2Fscygqd2hpY2gsIHR5cGVzPUZhbHNlKToKICAgICAgICAiIiJQcmludCB0aGUgbG9jYWwgdmFyaWFibGVzIGluIHRoZSBjYWxsZXIncyBmcmFtZS4iIiIKICAgICAgICBpbXBvcnQgaW5zcGVjdAogICAgICAgICMgY3VycmVudGZyYW1lKCkgZnJhbWUgaXMgcHJpbnRfbG9jYWxzLiBXZSB3YW50IHRoZSBjYWxsZXIncyBmcmFtZQogICAgICAgIGZyYW1lID0gaW5zcGVjdC5jdXJyZW50ZnJhbWUoKS5mX2JhY2sKICAgICAgICBsb2NhbHMgPSBmaW5kX2xvY2FscyhmcmFtZSkKICAgICAgICB3aGljaCA9IHNldCh3aGljaCkgaWYgd2hpY2ggZWxzZSBmaW5kX3doaWNoKGZyYW1lKQogICAgICAgIGxsID0ge2s6IHYgZm9yIGssIHYgaW4gbG9jYWxzLml0ZW1zKCkgaWYgayBpbiB3aGljaH0KICAgICAgICBpZiBub3QgbGw6CiAgICAgICAgICAgIHByaW50KCJwcmludF9sb2NhbHM6IG5vIGxvY2FscyIpCiAgICAgICAgICAgIHJldHVybgogICAgICAgIGlmIHR5cGVzOgogICAgICAgICAgICBwcmludCgiXG4iLmpvaW4oZiJ7a306IHt0eXBlKHYpLl9fbmFtZV9ffSDihpAge3Z9IiBmb3IgaywgdiBpbiBsbC5pdGVtcygpKSkKICAgICAgICBlbHNlOgogICAgICAgICAgICBwcmludCgiOyAiLmpvaW4oZiJ7a30g4oaQIHtyZXByKHYpfSIgZm9yIGssIHYgaW4gbGwuaXRlbXMoKSkpCgogICAgcmV0dXJuIHByaW50X2xvY2FscwoKcHJpbnRfbG9jYWxzID0gbWFrZV9wcmludF9sb2NhbHMoKQ==", "ZGVmIG1ha2VfcHJldHR5X2Fzc2VydCgpOgogICAgaW1wb3J0IHN5cwogICAgaW1wb3J0IElQeXRob24KICAgIGltcG9ydCBhc3QKICAgIGltcG9ydCBpbnNwZWN0CiAgICBpbXBvcnQgaW8KICAgIGltcG9ydCBpdGVydG9vbHMKICAgIGltcG9ydCBmdW5jdG9vbHMKICAgIGltcG9ydCBjb3B5CiAgICAKICAgIGdsb2JhbCBtYWtlX3ByZXR0eV9hc3NlcnQKICAgIGRlbCBtYWtlX3ByZXR0eV9hc3NlcnQKCiAgICBpZiBJUHl0aG9uLl9fdmVyc2lvbl9fID09ICI1LjUuMCI6CiAgICAgICAgIyBjb2xhYiBUT0RPCiAgICAgICAgZGVmIGdldF9hc3NlcnRfbGluZShmcmFtZSk6CiAgICAgICAgICAgIHJldHVybiBmcmFtZS5mX2JhY2suZl9iYWNrLmZfbG9jYWxzWyJub2RlIl0KICAgICAgICBkZWYgYXRfdG9wX2xldmVsKGZyYW1lKToKICAgICAgICAgICAgY29kZSA9IGZyYW1lLmZfYmFjay5mX2JhY2suZl9jb2RlCiAgICAgICAgICAgIHJldHVybiBjb2RlLmNvX2ZpbGVuYW1lLmVuZHN3aXRoKCJJUHl0aG9uL2NvcmUvaW50ZXJhY3RpdmVzaGVsbC5weSIpCiAgICAgICAgZGVmIGNhbl9hbm5vdGF0ZShmcmFtZSk6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQoKICAgIGVsaWYgSVB5dGhvbi5fX3ZlcnNpb25fXyA9PSAiOC40LjAiOgogICAgICAgICMgbGFiIGNvbXB1dGVycwogICAgICAgIGRlZiBnZXRfYXNzZXJ0X2xpbmUoZnJhbWUpOgogICAgICAgICAgICByZXR1cm4gZnJhbWUuZl9iYWNrLmZfYmFjay5mX2xvY2Fsc1sibm9kZSJdCiAgICAgICAgZGVmIGF0X3RvcF9sZXZlbChmcmFtZSk6CiAgICAgICAgICAgIGNvZGUgPSBmcmFtZS5mX2JhY2suZl9iYWNrLmZfY29kZQogICAgICAgICAgICByZXR1cm4gY29kZS5jb19maWxlbmFtZS5lbmRzd2l0aCgiSVB5dGhvbi9jb3JlL2ludGVyYWN0aXZlc2hlbGwucHkiKSBhbmQgY29kZS5jb19uYW1lID09ICJydW5fYXN0X25vZGVzIgogICAgICAgIGRlZiBjYW5fYW5ub3RhdGUoZnJhbWUpOgogICAgICAgICAgICByZXR1cm4gYXRfdG9wX2xldmVsKGZyYW1lKQoKICAgIGRlZiBpc19saXRlcmFsKGEpOgogICAgICAgIHRyeToKICAgICAgICAgICAgYXN0LmxpdGVyYWxfZXZhbChhKQogICAgICAgICAgICByZXR1cm4gVHJ1ZQogICAgICAgIGV4Y2VwdCBWYWx1ZUVycm9yOgogICAgICAgICAgICByZXR1cm4gRmFsc2UKICAgICAgICByZXR1cm4gRmFsc2UKCgogICAgZGVmIGFubm90YXRlX2NhbGwoZnJhbWUpOgogICAgICAgIGlmIG5vdCBjYW5fYW5ub3RhdGUoZnJhbWUpOgogICAgICAgICAgICByZXR1cm4KICAgICAgICAKICAgICAgICBleHByOiBhc3QuRXhwciA9IGdldF9hc3NlcnRfbGluZShmcmFtZSkKICAgICAgICBmb3Iga3dhcmcgaW4gZXhwci52YWx1ZS5rZXl3b3JkczoKICAgICAgICAgICAgaWYga3dhcmcuYXJnID09ICJnb3QiOgogICAgICAgICAgICAgICAgZ290ID0ga3dhcmcudmFsdWUKCiAgICAgICAgaWYgaXNpbnN0YW5jZShnb3QsIGFzdC5DYWxsKToKICAgICAgICAgICAgaWYgbm90IGlzaW5zdGFuY2UoZ290LmZ1bmMsIGFzdC5OYW1lKToKICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICBuYW1lID0gZ290LmZ1bmMuaWQKICAgICAgICAgICAgZnVuYyA9IGZyYW1lLmZfbG9jYWxzW25hbWVdCiAgICAgICAgICAgIGlmIG5vdCBoYXNhdHRyKGZ1bmMsIERFQlVHR0FCTEVfQVJHUyk6CiAgICAgICAgICAgICAgICByZXR1cm4KICAgICAgICAgICAgYXJncyA9IGdldGF0dHIoZnVuYywgREVCVUdHQUJMRV9BUkdTKQogICAgICAgICAgICBrd2FyZ3MgPSBnZXRhdHRyKGZ1bmMsIERFQlVHR0FCTEVfS1dBUkdTKQogICAgICAgICAgICBpZiBhcmdzIGlzIE5vbmUgb3Iga3dhcmdzIGlzIE5vbmU6CiAgICAgICAgICAgICAgICByZXR1cm4KICAgICAgICAgICAgYm91bmRhcmdzID0gaW5zcGVjdC5zaWduYXR1cmUoZnVuYykuYmluZCgqYXJncywgKiprd2FyZ3MpCgogICAgICAgICAgICByZXN1bHQgPSBpby5TdHJpbmdJTygpCiAgICAgICAgICAgIHBvcyA9IHJlc3VsdC53cml0ZShuYW1lKQogICAgICAgICAgICBwb3MgKz0gcmVzdWx0LndyaXRlKCIoIikKCiAgICAgICAgICAgIHNlcCA9ICcsICcKICAgICAgICAgICAgYXJnX3R1cGxlcyA9IFtdICAjIChhc3RfYXJnX3N0ciwgZXZhbHVhdGVkX2FyZywgc3RhcnQsIGxpbWl0KQoKICAgICAgICAgICAgIyBVc2UgYW4gaXRlcmF0b3IgaGVyZS4gSWYgYSBib3VuZGFyZyBpcyBub3QgY29uc3VtZWQgaGVyZSwKICAgICAgICAgICAgIyBpdCBtYXkgYmUgY29uc3VtZWQgbGF0ZXIgYnkgYSBwb3Mra3cgYXJnLgogICAgICAgICAgICBib3VuZGFyZ3NfaXRlciA9IGl0ZXIoYm91bmRhcmdzLmFyZ3MpCiAgICAgICAgICAgIGZvciBhc3RfYXJnLCBhcmcgaW4gemlwKGdvdC5hcmdzLCBib3VuZGFyZ3NfaXRlcik6CiAgICAgICAgICAgICAgICBhc3RfYXJnX3N0ciA9IGFzdC51bnBhcnNlKGFzdF9hcmcpCiAgICAgICAgICAgICAgICBhcmdfdHVwbGVzLmFwcGVuZCgoYXN0X2FyZ19zdHIsIGFyZywgcG9zLCBwb3MgKyBsZW4oYXN0X2FyZ19zdHIpKSkKICAgICAgICAgICAgICAgIHBvcyArPSBsZW4oYXN0X2FyZ19zdHIpICsgbGVuKHNlcCkKCiAgICAgICAgICAgIGZvciBhc3Rfa3dhcmcsIGt3YXJnIGluIGl0ZXJ0b29scy56aXBfbG9uZ2VzdChnb3Qua2V5d29yZHMsIGJvdW5kYXJnc19pdGVyKToKICAgICAgICAgICAgICAgIGFzdF9hcmdfc3RyID0gYXN0LnVucGFyc2UoYXN0X2t3YXJnKQogICAgICAgICAgICAgICAgYXJnX3R1cGxlcy5hcHBlbmQoKGFzdF9hcmdfc3RyLCBrd2FyZywgcG9zICsgbGVuKGFzdF9rd2FyZy5hcmcpICsgbGVuKCc9JyksIHBvcyArIGxlbihhc3RfYXJnX3N0cikpKQogICAgICAgICAgICAgICAgcG9zICs9IGxlbihhc3RfYXJnX3N0cikgKyBsZW4oc2VwKQoKICAgICAgICAgICAgcG9zIC09IGxlbihzZXApCiAgICAgICAgICAgIHJlc3VsdC53cml0ZShzZXAuam9pbih0WzBdIGZvciB0IGluIGFyZ190dXBsZXMpKQogICAgICAgICAgICByZXN1bHQud3JpdGUoJyknKQogICAgICAgICAgICByZXN1bHRfc3RyID0gcmVzdWx0LmdldHZhbHVlKCkKCiAgICAgICAgICAgIHlpZWxkIHJlc3VsdF9zdHIKCiAgICAgICAgICAgIG5vbmxpdGVyYWxzID0gW10gICMgKGV2YWx1YXRlZF9hcmcsIHJlc3VsdF9zdHIsIHN0YXJ0LCBsaW1pdCkKICAgICAgICAgICAgZm9yIF8sIGV2YWx1YXRlZF9hcmcsIHN0YXJ0LCBsaW1pdCBpbiBhcmdfdHVwbGVzOgogICAgICAgICAgICAgICAgaWYgbm90IGlzX2xpdGVyYWwocmVzdWx0X3N0cltzdGFydDpsaW1pdF0pOgogICAgICAgICAgICAgICAgICAgIG5vbmxpdGVyYWxzLmFwcGVuZCgoZXZhbHVhdGVkX2FyZywgcmVzdWx0X3N0cltzdGFydDpsaW1pdF0sIHN0YXJ0LCBsaW1pdCkpCgogICAgICAgICAgICB1bmRlcmxpbmVzID0gaW8uU3RyaW5nSU8oKQogICAgICAgICAgICBwb3MgPSAwCiAgICAgICAgICAgIGZvciBfLCBfLCBzdGFydCwgbGltaXQgaW4gbm9ubGl0ZXJhbHM6CiAgICAgICAgICAgICAgICBpZiAobGltaXQgLSBzdGFydCkgPCAzOgogICAgICAgICAgICAgICAgICAgIHBvcyArPSB1bmRlcmxpbmVzLndyaXRlKCcgJyAqIChzdGFydCAtIHBvcykpCiAgICAgICAgICAgICAgICAgICAgcG9zICs9IHVuZGVybGluZXMud3JpdGUoJ+KGkScpCiAgICAgICAgICAgICAgICAgICAgcG9zICs9IHVuZGVybGluZXMud3JpdGUoJ+KGkScgKiAobGltaXQgLSBwb3MpKQogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgICAgICBpZHggPSBzdGFydCArIChsaW1pdCAtIHN0YXJ0KSAvLyAyCiAgICAgICAgICAgICAgICBwb3MgKz0gdW5kZXJsaW5lcy53cml0ZSgnICcgKiAoc3RhcnQgLSBwb3MpKQogICAgICAgICAgICAgICAgI3BvcyArPSB1bmRlcmxpbmVzLndyaXRlKCfilZknKQogICAgICAgICAgICAgICAgcG9zICs9IHVuZGVybGluZXMud3JpdGUoJ+KGkScgKiAoaWR4IC0gcG9zKSkKICAgICAgICAgICAgICAgIHBvcyArPSB1bmRlcmxpbmVzLndyaXRlKCfihpEnKQogICAgICAgICAgICAgICAgcG9zICs9IHVuZGVybGluZXMud3JpdGUoJ+KGkScgKiAobGltaXQgLSBwb3MpKQogICAgICAgICAgICAgICAgI3BvcyArPSB1bmRlcmxpbmVzLndyaXRlKCfilZwnKQogICAgICAgICAgICB5aWVsZCB1bmRlcmxpbmVzLmdldHZhbHVlKCkKCiAgICAgICAgICAgIGRlZiBtYWtlX2JhcnNfYnVmKG5vbmxpdGVyYWxzLCBlbmQsIGV2YWxlZCk6CiAgICAgICAgICAgICAgICBidWYgPSBpby5TdHJpbmdJTygpCiAgICAgICAgICAgICAgICBwb3MgPSAwCiAgICAgICAgICAgICAgICBmb3IgaSBpbiByYW5nZShsZW4obm9ubGl0ZXJhbHMpIC0gMSk6CiAgICAgICAgICAgICAgICAgICAgXywgXywgc3RhcnQsIGxpbWl0ID0gbm9ubGl0ZXJhbHNbaV0KICAgICAgICAgICAgICAgICAgICBpZiAobGltaXQgLSBzdGFydCkgPCAzOgogICAgICAgICAgICAgICAgICAgICAgICBpZHggPSBzdGFydAogICAgICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgIGlkeCA9IHN0YXJ0ICsgKGxpbWl0IC0gc3RhcnQpIC8vIDIKICAgICAgICAgICAgICAgICAgICBwb3MgKz0gYnVmLndyaXRlKCcgJyAqIChpZHggLSBwb3MpKQogICAgICAgICAgICAgICAgICAgIHBvcyArPSBidWYud3JpdGUoJ+KUgicpCiAgICAgICAgICAgICAgICAgICAgcG9zICs9IGJ1Zi53cml0ZSgnICcgKiAobGltaXQgLSBwb3MpKQoKICAgICAgICAgICAgICAgIF8sIHJlc3VsdF9zdHIsIHN0YXJ0LCBsaW1pdCA9IG5vbmxpdGVyYWxzWy0xXQogICAgICAgICAgICAgICAgaWYgKGxpbWl0IC0gc3RhcnQpIDwgMzoKICAgICAgICAgICAgICAgICAgICBpZHggPSBzdGFydAogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICBpZHggPSBzdGFydCArIChsaW1pdCAtIHN0YXJ0KSAvLyAyICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgcG9zICs9IGJ1Zi53cml0ZSgnICcgKiAoaWR4IC0gcG9zKSkKICAgICAgICAgICAgICAgIHBvcyArPSBidWYud3JpdGUoJ+KUlCcpCiAgICAgICAgICAgICAgICBwb3MgKz0gYnVmLndyaXRlKCfilIAnICogKGVuZCAtIDEgLSBwb3MpKQogICAgICAgICAgICAgICAgcG9zICs9IGJ1Zi53cml0ZSgn4pW0JykKICAgICAgICAgICAgICAgIHBvcyArPSBidWYud3JpdGUocmVzdWx0X3N0cikKICAgICAgICAgICAgICAgIHBvcyArPSBidWYud3JpdGUoJyDiiZQgJykKICAgICAgICAgICAgICAgIHBvcyArPSBidWYud3JpdGUoc3RyKGV2YWxlZCkpCgogICAgICAgICAgICAgICAgcmV0dXJuIGJ1ZiwgcG9zCgogICAgICAgICAgICB3aGlsZSBub25saXRlcmFsczoKICAgICAgICAgICAgICAgIGJ1ZiwgcG9zID0gbWFrZV9iYXJzX2J1Zihub25saXRlcmFscywgbGVuKHJlc3VsdF9zdHIpICsgNCwgbm9ubGl0ZXJhbHNbLTFdWzBdKQogICAgICAgICAgICAgICAgeWllbGQgYnVmLmdldHZhbHVlKCkKICAgICAgICAgICAgICAgIGxhc3QgPSBub25saXRlcmFscy5wb3AoKQoKICAgIGRlZiBhc3NlcnRfZXF1YWwoKiwgd2FudCwgZ290LCBvdXQ9c3lzLnN0ZG91dCk6CiAgICAgICAgaWYgd2FudCA9PSBnb3Q6CiAgICAgICAgICAgIHByaW50KCJUZXN0IGNhc2UgcGFzc2VkLiIpCiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBmcmFtZSA9IGluc3BlY3QuY3VycmVudGZyYW1lKCkuZl9iYWNrCgogICAgICAgIGJveF9wYWRkaW5nID0gMgogICAgICAgIGhlYWRlciA9ICIgVGVzdCBjYXNlIGZhaWxlZC4gIgogICAgICAgIHdhbnRfbGluZSA9IGYie2JveF9wYWRkaW5nICogJyAnfVdhbnQ6IHtyZXByKHdhbnQpfSAodHlwZToge3R5cGUod2FudCkuX19uYW1lX199KSIKICAgICAgICBnb3RfbGluZSA9IGYie2JveF9wYWRkaW5nICogJyAnfUdvdDogIHtyZXByKGdvdCl9ICh0eXBlOiB7dHlwZShnb3QpLl9fbmFtZV9ffSkiCiAgICAgICAgCiAgICAgICAgaWYgY2FuX2Fubm90YXRlKGZyYW1lKToKICAgICAgICAgICAgYXNzZXJ0X2xpbmUgPSBmIntib3hfcGFkZGluZyAqICcgJ30+Pj4ge2FzdC51bnBhcnNlKGdldF9hc3NlcnRfbGluZShmcmFtZSkpfSIKICAgICAgICBlbHNlOgogICAgICAgICAgICBhc3NlcnRfbGluZSA9ICIiCiAgICAgICAgICAgIAogICAgICAgIGRlYnVnX2xpbmVzID0gbGlzdChhbm5vdGF0ZV9jYWxsKGZyYW1lKSkKICAgICAgICBpZiBkZWJ1Z19saW5lczoKICAgICAgICAgICAgZ290X2xpbmUgKz0gIiDihpAgIgogICAgICAgICAgICBwYWRkaW5nID0gbGVuKGdvdF9saW5lKQogICAgICAgICAgICBnb3RfbGluZSArPSBkZWJ1Z19saW5lc1swXQoKICAgICAgICBwYWRkZWRfZGVidWdfbGluZXMgPSBbXQogICAgICAgIGZvciBpLCBsaW5lIGluIGVudW1lcmF0ZShkZWJ1Z19saW5lcyk6CiAgICAgICAgICAgICAgICBpZiBpID09IDA6CiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgICAgIHBhZGRlZF9kZWJ1Z19saW5lcy5hcHBlbmQoJyAnICogcGFkZGluZyArIGxpbmUpCiAgICAgICAgICAgICAgICAKICAgICAgICBsaW5lX21heF9sZW4gPSBtYXgobGVuKGwpICsgYm94X3BhZGRpbmcgZm9yIGwgaW4gKGFzc2VydF9saW5lLCB3YW50X2xpbmUsIGdvdF9saW5lLCAqcGFkZGVkX2RlYnVnX2xpbmVzKSkKICAgICAgICBsaW5lX21heF9sZW4gPSBtYXgoMzIsIGxpbmVfbWF4X2xlbikKICAgICAgICBoZWFkZXJfZGFzaGVzID0gbGluZV9tYXhfbGVuIC0gbGVuKGhlYWRlcikKCgogICAgICAgIHByaW50KGZpbGU9b3V0KQogICAgICAgIHByaW50KCctJyAqIChoZWFkZXJfZGFzaGVzIC8vIDIpLCBlbmQ9IiIsIGZpbGU9b3V0KQogICAgICAgIHByaW50KGhlYWRlciwgZW5kPSIiLCBmaWxlPW91dCkKICAgICAgICBwcmludCgnLScgKiAoKGhlYWRlcl9kYXNoZXMgKyAxKSAvLyAyKSwgZW5kPSIiLCBmaWxlPW91dCkKICAgICAgICBwcmludChmaWxlPW91dCkKICAgICAgICBwcmludChmaWxlPW91dCkKCiAgICAgICAgCiAgICAgICAgaWYgYXNzZXJ0X2xpbmU6CiAgICAgICAgICAgIHByaW50KGFzc2VydF9saW5lLCBmaWxlPW91dCkKICAgICAgICAgICAgcHJpbnQoZmlsZT1vdXQpCgogICAgICAgIHByaW50KHdhbnRfbGluZSwgZmlsZT1vdXQpCiAgICAgICAgcHJpbnQoZ290X2xpbmUsIGZpbGU9b3V0KQogICAgICAgIGZvciBsaW5lIGluIHBhZGRlZF9kZWJ1Z19saW5lczoKICAgICAgICAgICAgcHJpbnQobGluZSwgZmlsZT1vdXQpCiAgICAgICAgCiAgICAgICAgcHJpbnQoZmlsZT1vdXQpCiAgICAgICAgcHJpbnQoJy0nICogbGluZV9tYXhfbGVuLCBmaWxlPW91dCkKICAgICAgICBwcmludChmaWxlPW91dCkKICAgICAgICAKICAgIERFQlVHR0FCTEVfQVJHUyA9ICJfZGVidWdnYWJsZV9hcmdzIgogICAgREVCVUdHQUJMRV9LV0FSR1MgPSAiX2RlYnVnZ2FibGVfa3dhcmdzIgoKICAgIGRlZiBkZWJ1Z2dhYmxlKGYpOgogICAgICAgIEBmdW5jdG9vbHMud3JhcHMoZikKICAgICAgICBkZWYgZygqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBhcmdzX2NvcHkgPSBjb3B5LmRlZXBjb3B5KGFyZ3MpCiAgICAgICAgICAgICAgICBrd2FyZ3NfY29weSA9IGNvcHkuZGVlcGNvcHkoa3dhcmdzKQogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgICAgICAgICAgYXJnc19jb3B5ID0gTm9uZQogICAgICAgICAgICAgICAga3dhcmdzX2NvcHkgPSBOb25lCiAgICAgICAgICAgIHJlc3VsdCA9IGYoKmFyZ3MsICoqa3dhcmdzKQogICAgICAgICAgICBzZXRhdHRyKGcsIERFQlVHR0FCTEVfQVJHUywgYXJnc19jb3B5KQogICAgICAgICAgICBzZXRhdHRyKGcsIERFQlVHR0FCTEVfS1dBUkdTLCBrd2FyZ3NfY29weSkKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdAogICAgICAgIHJldHVybiBnCiAgICAKICAgIHJldHVybiBhc3NlcnRfZXF1YWwsIGRlYnVnZ2FibGUKCmFzc2VydF9lcXVhbCwgZGVidWdnYWJsZSA9IG1ha2VfcHJldHR5X2Fzc2VydCgp")
for code in CODE:
exec(base64.b64decode(code), globals, locals)
f(globals(), locals())
del f
A queue is a data structure into which elements can be added (enqueued). When elements are removed from the queue (dequeued), they are removed in first-in-first-out order.
A queue is an abstract data structure. That is, any data structure which supports the queue operations (see below) can be used as a queue. There are many ways to implement the queue operations. Each implementation has its advantages and disadvantages.
The First-In-First-Out principle is similar to the concept of joining a line to buy food.
Let's say Michael joins the line, then Tyler joins the line, then Bereket joins the line.
Michael is at the the front of the line so he buys his food and gets served first. Then he leaves the line.
Now Tyler is at the start of the line so he buys his food and gets served next. Then he leaves the line.
Bereket is now at the start of the line so he buys his food, is served and then leaves the line.
Now the line is empty.
All queues support the following basic operations.
init_q()
: Constructs a new empty Queue.enqueue_q(queue, elem)
: Adds an element, elem, to the back of the Queue queue
.peek_q(queue)
: Returns the value of the frontmost element in the Queue queue
without removing it.dequeue_q(queue)
: Removes the frontmost element in the Queue queue
and returns its value.is_empty_q(queue)
: Tests whether or not Queue queue
is empty.Using the same example above of the line and a queue, food_line
:
'Michael joins the line' - enqueue_q(food_line, 'Michael')
'Tyler joins the line' - enqueue_q(food_line, 'Tyler')
'Bereket joins the line' - enqueue_q(food_line, 'Bereket')
'Michael is at the front of the line' - peek_q(food_line) # 'Michael'
'...gets served. Then he leaves the line' - dequeue_q(food_line)
'Now the line is empty' - is_empty_q(food_line) # True
So far we've just described the "abstract" interface for interacting with a Queue. But to actually use a Queue, we need a concrete implementation.
For this program, we will have you implement a queue using a Python list.
(Ponder: What might be the advantages of such an implementation? What are the disadvantages?)
lst.append(x)
will add x
to the right end of lst
lst.pop(i)
will remove the element in lst
at position i
@debuggable
def init_q(lst=None):
"""Constructs a new empty queue.
Arguments: Optional list of initial elements in the queue (Optional[list]).
Returns (Queue): The new empty queue.
Effects: None.
"""
if lst is None:
return []
return lst[:]
@debuggable
def enqueue_q(queue, elem):
"""Adds an element to the rear of the queue.
Arguments:
queue (Queue): The queue to which the element should be added.
elem (Any): The element to be added to the queue.
Returns: None.
Effects: Modifies `queue` by adding the new element.
"""
queue.append(elem)
@debuggable
def dequeue_q(queue):
"""Removes the element from the front of the queue and returns it.
queue must not be empty.
Arguments:
queue (Queue): The queue from which the front element should be removed.
Returns (any): The front element in the queue.
Effects: The front element is removed from the queue.
"""
return queue.pop(0)
@debuggable
def peek_q(queue):
"""Returns the element at the front of the queue, without removing it.
queue must not be empty.
Arguments:
queue (Queue): The queue from which the front element should be returned.
Returns (any): The front element in the queue.
Effects: None
"""
return queue[0]
@debuggable
def is_empty_q(queue):
"""Determines whether or not the queue is empty.
Arguments:
queue (Queue): The queue to be checked if it is empty or not
Returns (bool): True if the queue is empty or False if it is not empty
Effects: None
"""
return len(queue) == 0
# Test queues with integers.
queue = init_q()
assert_equal(want=None, got=enqueue_q(queue, 1)) # Queue contains [1]
assert_equal(want=None, got=enqueue_q(queue, 3)) # Queue contains [1, 3]
assert_equal(want=None, got=enqueue_q(queue, 2)) # Queue contains [1, 3, 2]
assert_equal(want=None, got=enqueue_q(queue, 5)) # Queue contains [1, 3, 2, 5]
assert_equal(want=1, got=peek_q(queue))
assert_equal(want=1, got=dequeue_q(queue)) # Queue contains [3, 2, 5]
assert_equal(want=3, got=peek_q(queue))
assert_equal(want=False, got=is_empty_q(queue))
# Test queues with other types.
queue = init_q()
enqueue_q(queue, "Hello")
enqueue_q(queue, "Goodbye")
enqueue_q(queue, [])
assert_equal(want="Hello", got=dequeue_q(queue))
assert_equal(want="Goodbye", got=dequeue_q(queue))
assert_equal(want=[], got=dequeue_q(queue))
# Test empty queues.
queue = init_q()
assert_equal(want=True, got=is_empty_q(queue))
Our queue implementation should work with string
's (or really any type), not just int
's.
Suppose TAs are waiting in two different lines for lunch. Write code that acts out the following scenario. There are two lines for lunch: one for chicken and one for pork.
"Annamira"
joins the line for chicken."Jabari"
joins the line for pork."Tyler"
joins the line for chicken."Natnael"
joins the line for chicken."Annamira"
is at the front of the line, she gets her chicken and then leaves the line."Annamira"
is still hungry, so she decides to join the line for pork as well to get a second lunch 😋."Jabari"
is served his pork and leaves the line.After the above shenanigans, "Tyler"
and "Natnael"
are still in line for chicken. "Annamira"
is in line for pork.
Enqueue the TAs into and dequeue the TAs from chickenLine
and porkLine
in the correct order to mimic the above scenario.
Note that some of the steps have already been executed. At the end, "Tyler"
and "Natnael"
should be in line for chicken, and "Annamira"
should be in line for pork.
Only use the queue operations!
# We have started the code for you:
chicken_line = init_q()
pork_line = init_q()
# Step 1: Annamira joins the queue for chicken.
enqueue_q(chicken_line, "Annamira")
# Step 2: Jabari joins the line for pork.
enqueue_q(pork_line, "Jabari")
# Step 3: Tyler joins the line for chicken.
# YOUR CODE HERE
# Step 4: Natnael joins the line for chicken.
# YOUR CODE HERE
# Step 5: The first person in the chicken line, Annamira, gets her chicken and
# leaves the line.
# YOUR CODE HERE
# Step 6: Annamira decies she is still hungry, so joins the pork line to get a
# second lunch.
# YOUR CODE HERE
# Step 7: The first person in the pork line, Jabari, gets his chicken and leaves
# the line.
# YOUR CODE HERE
# Tests. (Your strings should match the strings in the problem description.)
assert_equal(want="Tyler", got=dequeue_q(chicken_line))
assert_equal(want="Natnael", got=dequeue_q(chicken_line))
assert_equal(want=True, got=is_empty_q(chicken_line))
assert_equal(want="Annamira", got=dequeue_q(pork_line))
assert_equal(want=True, got=is_empty_q(pork_line))
Stacks are similar to queues in that items can be inserted and removed. However, unlike queues, the order of removal is reversed: the last item to be inserted is the first to be removed. Hence, the stack removes items in Last-In-First-Out (LIFO) order.
A stack is a data structure into which elements can be added (pushed). When elements are removed from the stack (popped), they are removed in last-in-first-out order.
A stack is also an abstract data structure. That is, any data structure which supports the stack operations (see below) can be used as a stack. There are many ways to implement the stack operations. Each implementation has its advantages and disadvantages.
All stacks support the following basic operations.
init_s()
: Constructs a new empty Stack.push_s(stack, elem)
: Adds an element, elem
, to the top of the Stack stack
.pop_s(stack)
: Removes the frontmost/popmost element in the Stack stack
and returns its value.top_s(stack)
: Returns the value of the frontmost/ element in the Stack stack
without removing it.is_empty_s(stack)
: Tests whether or not Stack stack
is empty.So far we've just described the "abstract" interface for interacting with a Stack. But to actually use a Stack, we need a concrete implementation.
For this program, we will have you implement a stack using a Python list.
lst.append(x)
will add x
to the right end of lst
.lst.pop()
will remove and return the last (rightmost) element in lst
.@debuggable
def init_s(lst=None):
"""Constructs a new empty stack.
Arguments: Optional list of initial elements in the stack (Optional[list]).
Returns (Stack): A new empty stack
Effects: None
"""
if lst is None:
return []
return lst[:]
@debuggable
def push_s(stack, elem):
"""Adds an element to the top of the stack
Arguments:
stack (Stack): The stack to push the element onto
elem (any): The element to be pushed onto the stack
Returns: None
Effects: Mutates the stack to add the element to the top of the stack.
Note that a new stack is not created.
"""
# YOUR CODE HERE
@debuggable
def pop_s(stack):
"""Remove the element on top of the stack.
Arguments:
stack (Stack): The stack to pop the element from
Returns (any): The element on the top of the stack
Effects: Modifies `stack` to remove the top element.
Note that a new stack is not created.
"""
# YOUR CODE HERE
@debuggable
def top_s(stack):
"""Returns the value of the topmost element on the stack without removing it
Arguments:
stack (Stack): The stack to find the top element of.
Returns (any): The element on the top of stack.
Effects: None
"""
# YOUR CODE HERE
@debuggable
def is_empty_s(stack):
"""Checks if the stack is empty.
Arguments:
stack (Stack): The stack to be checked if it is empty
Returns (bool): True if the stack is empty or False if it is not
Effects: None
"""
# YOUR CODE HERE
# Test stacks with integers.
stack = init_s()
assert_equal(want=None, got=push_s(stack, 1)) # Stack contains [1]
assert_equal(want=None, got=push_s(stack, 3)) # Stack contains [1, 3]
assert_equal(want=None, got=push_s(stack, 2)) # Stack contains [1, 3, 2]
assert_equal(want=None, got=push_s(stack, 5)) # Stack contains [1, 3, 2, 5]
assert_equal(want=5, got=pop_s(stack))
assert_equal(want=2, got=pop_s(stack)) # Stack contains [1, 3, 2, 5]
assert_equal(want=3, got=top_s(stack))
assert_equal(want=False, got=is_empty_s(stack))
# Test questacksues with other types.
stack = init_s()
push_s(stack, "Hello")
push_s(stack, "Goodbye")
push_s(stack, [])
# Stacks pop in last-in-first-out.
assert_equal(want=[], got=pop_s(stack))
assert_equal(want="Goodbye", got=pop_s(stack))
assert_equal(want="Hello", got=pop_s(stack))
# Test empty stacks.
stack = init_s()
assert_equal(want=True, got=is_empty_s(stack))
Impressive✨! We are finally done implementing our Queue and Stack classes. Let's move now to some problems!
Write a function that reverses a list using a stack. Do not use list slicing or the reverse
or reversed
functions. Don't forget to return a list (and not a stack).
@debuggable
def rev(lst):
"""Reverses the given list `lst` using a stack.
Arguments: lst (list) The list to be reversed.
Returns (list): The reversed list.
Effects: None.
"""
# Test your function
assert_equal(want=[4, 3, 2, 1], got=rev([1, 2, 3, 4]))
assert_equal(want=[1, 2, 3, 4], got=rev([4, 3, 2, 1]))
assert_equal(want=[12, 10, 8, 6 ,4, 2], got=rev([2, 4, 6, 8, 10, 12]))
Crossover episode! In this question we will merge two sorted queues into a new sorted queue.
You may want to refer back to our code that merges two sorted lists. If you do so, think what needs to be changed for queues. (Hint: you no longer need to keep the two pointers/fingers for each list!)
Remember to access queues only using the five queue operations above.
@debuggable
def merge(queue1, queue2):
"""Merges two sorted queues into a new sorted queue.
Arguments: q1 (Queue of ints), q2 (Queue of ints)
Returns: (Queue of ints)
Side effects: Empties q1 and q2.
"""
# YOUR CODE HERE
# Test your function
queue1, queue2 = init_q([1, 4, 5, 6]), init_q([2, 3, 5, 5, 10])
assert_equal(want=init_q([1, 2, 3, 4, 5, 5, 5, 6, 10]), got=merge(queue1, queue2))
queue1, queue2 = init_q([]), init_q([])
assert_equal(want=init_q([]), got=merge(queue1, queue2))
queue1, queue2 = init_q([1, 1, 1, 1]), init_q([2, 2, 2, 2])
assert_equal(want=init_q([1, 1, 1, 1, 2, 2, 2, 2]), got=merge(queue1, queue2))
You are given a string that records a sequence of keystroke. There are two possibilities for each keystroke (character is the string):
a-z
or A-Z
.'*'
which indicates that backspace was pressed.You will implement a function apply_backspace
that applies backspaces to a string. Some examples:
"Orrrr**" --> "Orr"
"Bri*yan" --> "Bryan"
"I'm tired*****having fun! --> I'm having fun!"
"Bye***" --> ""
"**" --> ""
because pressing backspaces on an empty string deletes nothing..."Hi****" -> ""
for the same reasonHint: To turn a list of characters back into a string, use the string.join
function. For example, suppose chars = ['a', 'b', 'c']
. Then ''.join(chars)
would return the string "abc"
.
Hint: You might want to use the rev
reverse function you defined above.
@debuggable
def apply_backspace(s):
"""Applies backspaces to string s.
For every occurrence of *, deletes the most recent letter.
Arguments:
s (str): A string with letters and backspaces.
Returns (str): A string with all backspaces applied.
Effects: None.
"""
# YOUR CODE HERE
# Test your function
assert_equal(want="Orr", got=apply_backspace("Orrrr**"))
assert_equal(want="Bryan", got=apply_backspace("Bri*yan"))
assert_equal(want="I'm having fun!", got=apply_backspace("I'm tired*****having fun!"))
assert_equal(want="", got=apply_backspace("Bye***"))
assert_equal(want="", got=apply_backspace("**"))
assert_equal(want="", got=apply_backspace("Hi****"))
You are given a string that contains only the characters '('
or ')'
. You will write a function is_valid
that checks whether the string is valid if all parentheses are balanced---correctly matched. More formally, a string s
is valid if:
(
is matched with a subsequent )
.)
's than (
'.Here are some examples:
"()"
is valid."(())
is valid."()()"
is valid.""
is valid (because there are no parentheses at all...)"("
is invalid.")"
is invalid."())"
is invalid."(()"
is invalid.@debuggable
def is_valid(s):
"""Checks whether a string of parentheses is balanced.
Arguments: s, a string consisting of parens; '(' or ')'
Returns (bool): Whether `s` is correctly balanced.
Effects: None
"""
# YOUR CODE HERE
assert_equal(want=False, got=is_valid("())")) # Too many closing parens.
assert_equal(want=False, got=is_valid("(")) # No matching closing parens.
assert_equal(want=False, got=is_valid("((")) # No matching closing parens.
assert_equal(want=False, got=is_valid("()(")) # No matching closing parens.
assert_equal(want=False, got=is_valid("(((()))")) # No matching closing parens.
assert_equal(want=True, got=is_valid("(())")) # Correctly balanced.
assert_equal(want=False, got=is_valid(")")) # Too many closing parens.
assert_equal(want=True, got=is_valid("")) # Empty string is balanced.
assert_equal(want=True, got=is_valid("()()"))
assert_equal(want=True, got=is_valid("()()"))
assert_equal(want=False, got=is_valid("()))")) # Too many closing parens.
assert_equal(want=False, got=is_valid("((()())))")) # Too many closing parens.
Modify your code from 1.1 to handle different kinds of square brackets []
and curly brackets {}
.
You are given a string consisting of any of the characters ()[]{}
. A string is valid if:
Examples:
"{[]{()}}"
is valid."[{}{}(]"
is invalid.@debuggable
def is_valid(s):
"""Checks whether a string of parentheses, brackets, and square brackets is valid.
Arguments:
s (str): String to be checked, consisting of the characters
'(', ')', '[', ']', '{', or '}').
Returns (bool): Whether the string has balanced
parenstheses/brackets/square brackets.
Effects: None.
"""
# YOUR CODE HERE
## Test your solution
assert_equal(want=True, got=is_valid("{[]{()}}"))
assert_equal(want=True, got=is_valid(""))
assert_equal(want=False, got=is_valid("[{}{}(]")) # Opening parens, but closing square bracket
assert_equal(want=False, got=is_valid("]{}([{])}")) # No matching opening square bracket for first character
assert_equal(want=False, got=is_valid("[()(){}}")) # Last character should be a closing square bracket instead of closing bracket
assert_equal(want=False, got=is_valid("[{[[{")) # Unmatched opening brackets.
assert_equal(want=False, got=is_valid("]})]}")) # Unmatched closing brackets.
assert_equal(want=True, got=is_valid("()"))
assert_equal(want=True, got=is_valid("()[]{}"))