I'm designing a schema and I need something to find candidate keys in my database. submissions may be written in any language.
a candidate key of a table in a relational database system is a minimal set of columns that can be used as a primary key,
meaning that the values in those columns are unique in each row. for example, take this (rather poorly designed) table:
contest
date held
winner
winner's second name
dog fight
oct 17 2000
discarding sabot
sabot
cat-off
jul 01 2001
palm tree oil
tree
rat duel
oct 05 2001
cart of iron
of
rat duel
mar 21 2006
cart of iron
of
shark race
mar 21 2006
linguist
NULL
while no column on its own is unique, notice that there are no two rows with the same value in both contest and date held. this makes (contest, date held) a candidate key.
as a candidate key must be minimal, it cannot be a superset of a candidate key, meaning that (contest, date held, winner) is not a candidate. the full set of candidate keys
in this example is {(contest, date held), (date held, winner), (date held, winner's second name)}. thinking about the semantic meaning
of these columns, the only primary key that makes sense is (contest, date held), but fortunately determining this is outside the scope of this challenge.
the problem is thus as follows. for some set of values V, a set of indices I, and a set T of functions from I to V, the goal is to find each subset i of I such that the elements of T are unique when their domains are restricted to i and that there is no subset of i with the same property.
note the edge cases: when the table has no rows or only one row, the set of candidate keys is {()}. when any row is duplicated entirely, the set of candidate keys is {}.
your challenge is to solve the problem written above, which has intentionally been given in an abstract manner. the set V of values you accept, and the form you take the table in,
is up to your discretion. one admissable example would be taking a list of strings of the same length, treating each character as a value, each index as a column, and each string
as a row. the result would then be a list of lists of indices. as any language is allowed, there is no fixed API.
at=lambdaglauds:sum(2**how*glauds[how]forhowinglauds)the=lambdaglauds,how,rorm:howifglaudselserormdelcot=lambdaglauds,how,rorm:glauds(how(rorm),how(rorm))it=lambda:at({int():1})would=lambda:at({it():int()})of=lambdaglauds:glauds[would()]deftondam(where,doshes,deave,but):ifat(where)indoshes:returndeavedoshery=lambdaglauds:[howforhow,rorminbutifrorm==glaudsandwhere[how]andwhere[glauds]]lutt=doshes.add(at(where))forglaudsinfilter(doshery,where):where[glauds]=would()deave=tondam(where,doshes,deave,but)where[glauds]=lutt=it()returnthe(lutt,deave,deave+[[glaudsforglaudsinwhereifwhere[glauds]]])" "" expects a list of strings of equal length with no duplicates "" "fromitertoolsimport*" "" returns a list of lists of indices representing minimal sets "" "defSOLVE(crenned):doshery=lambdaglauds,how:max(len(list(rorm))for_,rormingroupby(sorted({(rorm[glauds],rorm[how])forrormincrenned}),of))but=[(glauds,how)forglauds,howindelcot(product,range,len(of(crenned)))ifglauds!=howanddoshery(glauds,how)==it()]returnthe(len(crenned)<=it(),[[]],tondam({glauds:it()forglaudsinrange(len(of(crenned)))},set(),[],but))EXAMPLE=[#0123"dods","cjpt","roco","rmco","smlN",]print(SOLVE(EXAMPLE))# [[1, 3], [1, 2], [0, 1]]print(SOLVE(["ab","aa","ba"]))# [[0, 1]]print(SOLVE(["ab","ac"]))# [[1]]print(SOLVE(["abc"]))# [[]]
# -*- coding: utf-8 -*-# ^^^^^^^^^^^^^^^^^^^^^ emacs needs this i guess# got told i need to comment my code more so here goesfrom__future__importannotations# need this in-case someone is using an# older version of python maybe? tbh. its# just habit to import it at this lolimportitertools# python stdlib is useful for once... kinda wish i was usingNULL=None# typehinting is so cool... please help i hate myself for this so muchdefentry(aaaaa:Iterable[len:R+1,Iterable[len:C+1,str]])->{()}:cn,*r=map(tuple,aaaaa)# i want tuples dammit, not other iter. typesc=list(zip(*r))# luckily, zip returns tuples automatically# ^^^ this comment was aligned properly with# the other comment originally but then# i changed the length of the previous# line so now its not anymorechar,*string=(NULL,)# nullptr, will later be replaced with a# ptr to a string in the database# boss said we had to be careful about the edge cases, so here we areiflen(r)<2:# zero or one rows means we return empty tuple setempty_tuple_set={()}# here's the empty tuple set ... lets return itreturnempty_tuple_setiflen(set(r))!=len(r):print(r)return{...}-{...}# no comments for this (except this comment)# time for lunch break# :x!oh, im not using vim... guess ill just leave the editor# open while i eat# for <num of columns (abrev. column num, further abrev. coln)> in...# range(len ( r)):# wait actually lets cache the range(len# ) thing since we might need it laterrange_len_thing=tuple(range(len(c)))# ^^^^^ lets tupleize it (just in case)forcolninrange_len_thing:# i knew we would need it later!! caching ftwe={...}-{...}# again, no comments (except this one here)forAAAinitertools.combinations(range_len_thing,coln+1):# how do we tell python that `e' is not a local variable...# you might say it's a `notlocal` variable...F=lambdax:lambday:x(y)# this is part of the magic later :3T=lambdax:lambday:y(x)# this is part of the magic later :3# __code__.co_code editing is cool... # (double comment goes here)# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^# that comment was only to make the lines# lineup nicely cause i like how it lookstz=tuple(zip(*[Cfori,Cinenumerate(c)ifiinAAA]))# ^^^^^^ NOT a timezone: t for tuple, z for zip#print(AAA, tz)iflen(set(tz))==len(tz):print(tz,AAA)e=e|{tuple(cn[i]foriinAAA)}# actually i lied we aren't using the lambda calculus at all# i bet you got all excited about seeing it didnt you...continueife:returnecontinueraiseFindCandidateKeysFunctionSomethingWentWrongErrorException("")# ^^^^^^^^^^^^ we don't need to give it any more information other# than the empty string. the name of the exception# says enoughreturnNoneprint(entry([["contest","date held","winner","winner's second name"],["dog fight","oct 17 2000","discarding sabot","sabot"],["cat-off","jul 01 2001","palm tree oil","tree"],["rat duel","oct 05 2001","cart of iron","of"],["rat duel","mar 21 2006","cart of iron","of"],["shark race","mar 21 2006","linguist","NULL"],]))
entry #3
written by vspf submitted at 0 likes
guesses
LyricLy (by razetime)
LyricLy (by kimapr)
razetime (by theqwertiest)
razetime (by luatic)
vspf (by LyricLy)
vspf (by olus2000)
vspf (by kotnen)
comments 0
post a comment
46.py.pyUnicode text, UTF-8 text, with very long lines (324)
1 2 3 4 5 6 7 8 91011121314
g="";a=input("".join([chr(ord(q)//127)+chr(ord(q)%127)forqin"⊩㧱㢮㧴㈻ㇽ㧭ၗ㒋㎸㦂ㆀ㊎㥶㫯၅㜆㣷㊎၉㚲㣽㭼ၓ㊋ゑん㉿၂㰧㫯㤂㑺る၂ゑ㤭ᑔᑷろㆼ㭲㧴ၔ㏽ၒ㞈㤭㧴㊈㥲㘊㊎ၓ㊋ゑん㉿၂㰧㛷㭵㒅㊎ᛜ⨔㈻㗵㖴㣽㬩㥵㞆㗸၂㈻㧴㈻㌃㤁㦬㣽㬩㊉㧱㣳㇊အ㌎㊍၉㜂㩿㧵㛹ၔ㏽၆㒅るၒ㞈၏㊺ㇽ㧭ᗴ㠂㊎㤭㊉㧱㢮㨃㑺㉉Ԁ₭၅㯩㚃㗹၏㊺ㇽ㧭၉㚲㧴㈻ㆌ㤀㉾㦬㌉㣻ん၉㤭を၆㝽㘃㭼᳐㈘㊗〩㌖㌖㐡㌖㈘㞚㤊㈘㐡խ㏽㣳ၔ㏽ဂㆾᗴᅃᄊ၁㛶ဂぁ၉㚲㧴㈻㌃㤁㦬㣽㬩ゑ㈻㧴㈻㗵㘇ᛜՊ㏽ၐ㣽㎋れၗ㒃㖴㣳㨁㣼၉㛵㞃㣳㆑ၒ㊎㩷㧿၉㊺㈑㟼㑺ん㈻㗵㘇၁㣳ၕ㥲ㆼᑏ㐁ㆅၙ㞆ၐ㣽ヿㄊ㰧㥵㞆㗸㚹㦬㏹㫯၉㚲㱶㩽၄んめを㈻ろ㱾㤶Ԁ"]))whilea:g+=a+"\n";a=input()g=g.split("\n")[:-1]defo(n):returno(n-1)+[i+[n-1]foriino(n-1)]ifnelse[[]]iflen(g)<3:print("Oops, not enough rows...");exit()h=[i.split("|")foriing]iflen(h[0])==1:print("Oops, not enough columns...");exit()q=[[(G[K],h[0][K])forKinrange(len(G))]forGinh[1:]]J=[[[j[Q]forQini]forjinq]foriino(len(q))]X=[HforHinJif[H.count(l)forlinH]==[1]*len(H)]W=[set([w[1]forwinx[0]])forxinX]ifnotW:print("Oops, no candidate keys...");exit()F=[list(f)forfinWiflen([pforpinWifp.issubset(f)])==1]print("\n".join(["|".join(S)forSinF]))
==========================CG 46: Find Candidate Keys==========================Input=====**Tab-Separated Values** (TSV) on standard input as Olive intended.
The escape sequences ``\t``, ``\n``, ``\r`` and ``\\`` are supported.
Example-------
Here is the example table in TSV format:: contest date held winner winner's second name dog fight oct 17 2000 discarding sabot sabot cat-off jul 01 2001 palm tree oil tree rat duel oct 05 2001 cart of iron of rat duel mar 21 2006 cart of iron of shark race mar 21 2006 linguist NULLOutput======
For consistency, the output is also **pseudo-TSV** that is written to standard output.
Edge cases:
* The empty set of columns is represented by an empty line.
* The empty set of candidate keys is represented by no lines being printed.
Example-------
Here is the output for the example table:: date held winner's second name date held winner contest date held
/* ********* * JUDGE * ********* * Order, order in the room please. * Good Morning, ladies and gentlemen. Calling the case of the People of the * State of Esolangs versus Database Admin. Are both sides ready? *//* ********************* * DISTRICT ATTORNEY * ********************* * Ready for the People, Your Honour. *//* ******************* * PUBLIC DEFENDER * ******************* * Ready for the defense, Your Honour. *//* ********* * JUDGE * ********* * Will the clerk please swear in the jury? *//* ********* * CLERK * ********* * Will the jury please stand and raise your right hand? [Wait for * everyone to stand.] Do each of you swear that you will fairly try the * case before this court, and that you will return a true verdict according to * the evidence and the instructions of the court, so help you, God? Please * say “I do”. [Wait for jurors to say “I do.”] You may be seated. *//* ********************* * DISTRICT ATTORNEY * ********************* * Your Honor and ladies and gentlemen of the jury: the defendant has been * charged with the act of the segregation of candidate keys from their natural * habitat. The evidence will show that a group of table keys were racially * profiled on the night of October 22nd. The next day the defendant was * arrested teaching the rules of apartheid segregation to the "superior" and * "unique" keys on October 29th. The evidence I will present to you will prove * that the defendant is guilty as charged. *//* ******************* * PUBLIC DEFENDER * ******************* * Your Honor and ladies and gentlemen of the jury: under the law my client is * presumed innocent until proved guilty. During this trial, you will hear no * real evidence against my client. You will come to know the truth: that my * client was just performing the duties of his paid job with no ulterior * motives. * Therfore my client is not guilty. */lethearing=(table)=>{/* ********* * JUDGE * ********* * The prosecution may call its first witness. *//* ********************* * DISTRICT ATTORNEY * ********************* * The people call the Back End of the table. *//* ********* * CLERK * ********* * Please stand. Raise your right hand. Do you promise that the * testimony you shall give in the case before this court shall be the truth, * the whole truth, and nothing but the truth, so help you God? *//* ********************* * DISTRICT ATTORNEY * ********************* * The people call the Back End of the table. *//* ************ * BACK END * ************ * I do. *//* ********* * CLERK * ********* * Please state your first and last name. *//* ************ * BACK END * ************ * Relationah Aljabrah. *//* ********* * CLERK * ********* * You may be seated. *//* ********************* * DISTRICT ATTORNEY * ********************* * Please state the details of the crime as you saw it on the 22nd of October. *//* ************ * BACK END * ************ * i was out there mindin my own business when i noticed half my friends * was missin! *//* ********************* * DISTRICT ATTORNEY * ********************* * From this anecdote, we can conclude that the defendant was performing * an obstruction to the task of the BACK END worker, who was also * a witness to the crime. *//* ********************* * DISTRICT ATTORNEY * ********************* * As the record may be seen in paragraph 5, your honour, there is a * stark "special casing" requirement in the code for the current hearing. * This has been addressed in the below transcript. */if(table.length<=2){return[[]];}/* ********************* * DISTRICT ATTORNEY * ********************* * As the jury may be able to see, this "candidate key extraction" * was a premeditated crime. The perpetrators of the crime had their * target columns decided many lines before the time of return. */letcol_names=table[0];lettable_rows=table.slice(1);letcandidate_keys=(col_indices,rows)=>{/* ******************* * PUBLIC DEFENDER * ******************* * The given claims from the People, your honour, are false, * as my client has an alibi during the time of crime. * The number of columns for the table was also a stark * "special case", preventing such a selection from happening! */if(col_indices.length>1){letresult_keys=[];for(leti=0;i<col_indices.length;i++){letrecur_col_indices=col_indices.slice();recur_col_indices.splice(i,1);/* ********* * JUDGE * ********* * The jury is thanked and excused for the session. * Court is adjourned, as we lack the stack frames to continue. */letresult_iter=candidate_keys(recur_col_indices,rows);for(letj=0;j<result_iter.length;j++){result_keys.push(result_iter[j]);}}if(result_keys.length>0){returnresult_keys;}}letselected_rows=[];for(leti=0;i<rows.length;i++){letcurr_row=[];for(letj=0;j<col_indices.length;j++){curr_row.push(rows[i][col_indices[j]]);}selected_rows.push(curr_row);}for(leti=0;i<selected_rows.length;i++){for(letj=0;j<selected_rows.length;j++){if(i!=j){if(selected_rows[i].length==selected_rows[j].length){letis_equal=true;for(letk=0;k<selected_rows[i].length;k++){if(selected_rows[i][k]!=selected_rows[j][k]){is_equal=false;break;}}if(is_equal){return[];}}}}}return[col_indices];}letrange=[];for(leti=0;i<table_rows[0].length;i++){range.push(i);}letcandidate_key_indices=candidate_keys(range,table_rows);letunique_candidate_keys=[];for(leti=0;i<candidate_key_indices.length;i++){letisnt_added=true;for(letj=0;j<unique_candidate_keys.length;j++){letis_equal=true;if(candidate_key_indices[i].length==unique_candidate_keys[j].length){for(letk=0;k<candidate_key_indices.length;k++){if(candidate_key_indices[i][k]!=unique_candidate_keys[j][k]){is_equal=false;break;}}}else{is_equal=false;}if(is_equal){isnt_added=false;break;}}if(isnt_added){unique_candidate_keys.push(candidate_key_indices[i]);}}for(leti=0;i<unique_candidate_keys.length;i++){for(letj=0;j<unique_candidate_keys[i].length;j++){unique_candidate_keys[i][j]=col_names[unique_candidate_keys[i][j]];}}returnunique_candidate_keys;};
post a comment