x2ten Reflections on WriteUp 2 1

advertisement
ReflectionsonWriteUp2
1
First,let'sgoovertheproblemsinthepracticeproblemset.
Thex2tenmethod
Defineamethodnamedx2tenthatacceptsaStringandanintasinput,andreturns(asanint)the
base10interpretationoftheStringinterpretedasanumberinthebasegivenbytheintinput.For
example,x2ten(“1101”,2)mustreturn13.Forbasesbeyond10useupper-caselettersstarting
with‘A’asdigits.Inbase16thedigitsusedaretherefore‘0’through‘F’.Yourmethodmustwork
withbasesintherange2through36.Forillegalinputs(e.g.null,Stringswithillegalcharacters,
orbasesoutsidetheallowablerange)themethodmustreturn-1.
Forthismethoditishelpfultorememberhownumbersystemswork.Recallthatasequenceof
base10digits,like7453,hasthefollowinginterpretation:
7453 = 7 ∗ 10) + 4 ∗ 10+ + 5 ∗ 10, + 3 ∗ 10- Wecanfactorthis:
= (7 ∗ 10+ + 4 ∗ 10 + 5) ∗ 10 + 3
= ((7 ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
= (((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
Whybotheradding0*10insidetheinnermostsetofparentheses?Iwanttofindaformthatlends
itselftoexpressionasaloop.The0representstheinitialvalueofavariableinwhichthecodewill
incrementallyaccumulatetheanswer.Doyouseethepattern?
= (((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
= (((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
= (((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
= (((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
Thissamestructureholdforanybase.Ateachstepwehave:
answer*base+digit
Ifwethinkabouttheprogressionofthiscomputationatdiscretetimesteps(indicatedby
subscripts):
answer0=0
answer1=answer0*base+digit0
answer2=answer1*base+digit1
…
Moregenerally:
answer0=0
answeri+1=answeri*base+digiti
Expressingthisiscode,here'sthebasicidea:
public int x2ten(String input, int base) {
int answer = 0;
for (int i=0; i<input.length(); i++) {
char ch = input.charAt(i);
int digit = char2digit(ch);
answer = answer * base + digit;
}
return answer;
}
ReflectionsonWriteUp2
2
Highlightingtherelevantbits,andaddingsomesubscriptstomaketheconnectionsmoreclear:
public int x2ten(String input, int base) {
int answer0 = 0;
for (int i=0; i<input.length(); i++) {
char ch = input.charAt(i);
int digit = char2digit(ch);
answeri+1 = answeri * base + digiti;
}
return answer;
}
Theloopconsidersthedigitsofthenumberfromlefttoright.SincecharactersintheinputString
arenotbase10digits,butASCII/Unicoderepresentationsofthedigits,wecallthechar2value
methodtogetthevalueofeachdigit.Yourfavoriteprogramminglanguagemighthavealibrary
methodtodothisforyou,butitisnotadifficultmethodtowrite;hereitiswithsomesanitycheckingthatwe'lltakeuseinjustabit:
private int char2digit(char ch) {
if ('0' <= ch && ch <= '9') { return ch - '0'; }
if ('A' <= ch && ch <= 'Z') { return ch - 'A' + 10; }
return -1;
}
Theproblemaskedustoalsotakeintoaccountsome"illegal"inputs.Withthatcodeincluded,
here'sapossiblecompletesolution:
public int x2ten(String input, int base) {
if (badInput(input, base)) { return -1; }
int answer = 0;
for (int i=0; i<input.length(); i++) {
char ch = input.charAt(i);
int digit = char2digit(ch);
if (digit == -1 || digit >= base) { return -1; }
answer = answer * base + digit;
}
return answer;
}
private int char2digit(char ch) {
if ('0' <= ch && ch <= '9') { return ch - '0'; }
if ('A' <= ch && ch <= 'Z') { return ch - 'A' + 10; }
return -1;
}
private boolean badInput(String input, int base) {
return input == null || base < 2 || base > 36;
}
ReflectionsonWriteUp2
3
Theten2xmethod
Defineamethodnamedten2xthatacceptstwointsasinput,andreturnsaStringrepresentingthe
firstint(abase10number)expressedinthebasegivenbythesecondint.Forexample,
ten2x(13,2)mustreturn“1101”.Yourmethodmustworkwiththesamerangeofbasesasin
question1.Forillegalinputsthemethodmustreturnnull.
Toseehowtostructurethismethodwewillagainrecallthestructureofanumber.Recallthe
factoredformwecameupwithfor7453:
(((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
Let'scolor-codethestructureagain:
(((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5) ∗ 10 + 3
Let'slookatwhathappenswhenwedividethisby10.Payattentiontothequotientandthe
remainder:
quotientof
(((-∗,-12)∗,-13)∗,-14)∗,-1)
,-
(((-∗,-12)∗,-13)∗,-14)∗,-1)
remainderof
Wecanofcourserepeatthis…
quotientof
quotientof
,-
((-∗,-12)∗,-13)∗,-14
,-
remainderof
…again…
= (((0 ∗ 10 + 7) ∗ 10 + 4) ∗ 10 + 5)
,-
,-
remainderof
…andagain…
= ((0 ∗ 10 + 7) ∗ 10 + 4)
((-∗,-12)∗,-13)∗,-14
(-∗,-12)∗,-13
(-∗,-12)
= 5
= (0 ∗ 10 + 7)
(-∗,-12)∗,-13
,-
= 3
= 4
quotientof
= 0
,
-∗,-12
remainderof
= 7
,
…untilthequotientiszero.Theremaindersarethedigitsofthenumberfromrighttoleft.This
workswithotherbasestoo.Forexample,toobtainthebase2digitsofthebase10number13,just
keepdividing13by2,payingattentiontothequotientsandremainders:
13/2hasquotient6,remainder1
6/2hasquotient3,remainder0
3/2hasquotient1,remainder1
1/2hasquotient0,remainder1
ReflectionsonWriteUp2
1101isindeedthebase2representationofthebase10number13.
Howdowecapturethisincode?Consideragaintherecurringstepthatwearegoingtoputintoa
loop:
initialconditions
input0=theoriginalnumber
generalformulae
quotienti=inputi/base
remainderi=inputi%base
inputi+1=quotienti
Incode:
public String ten2x(int input, int base) {
String answer = "";
do {
int quotient = input / base;
int remainder = input % base;
input = quotient;
char ch = digit2char(remainder);
answer = ch + answer;
} while (input > 0);
return answer;
}
Highlightingthebitsfromabove:
public String ten2x(int input0, int base) {
String answer = "";
do {
int quotienti = inputi / base;
int remainderi = inputi % base;
inputi+1 = quotienti;
char ch = digit2char(remainder);
answer = ch + answer;
} while (input > 0);
return answer;
}
Weshouldagaindosomesanitycheckingontheinput:
public String ten2x(int input, int base) {
if (badInput(input, base)) { return null; }
String answer = "";
do {
int quotient = input / base;
int remainder = input % base;
input = quotient;
char ch = digit2char(remainder);
answer = ch + answer;
} while (input > 0);
return answer;
}
private boolean badInput(int input, int base) {
return input < 0 || base < 2 || base > 36;
}
4
ReflectionsonWriteUp2
5
ThesumOfDigitsmethod
DefineamethodnamedsumOfDigitsthatacceptsaStringandreturnsanintwhichisthesumof
thedigitscontainedintheString.Forexample,sumOfDigits(“1234”)mustreturn10,and
sumOfDigits(“338DavisHall,BuffaloNY14260”)mustreturn27.
Basicidea:loopthroughcharactersintheinputString,oneatatime.Whenonerepresentsadigit,
getvalueandaddtoanswer.Here'sonepossiblesolution:
public int sumOfDigits(String input) {
int answer = 0;
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (isDigit(ch)) {
answer = answer + (ch - '0');
}
}
return answer;
}
private boolean isDigit(char ch) {
return '0' <= ch && ch <= '9';
}
Thex2ymethod
Defineamethodnamedx2ythatacceptsaStringandtwointsasinput,andreturns(asaString)
thebaseyinterpretationoftheinputString,assumingitisinbasex.Thus,x2y(“1101”,2,10)must
return“13”,andx2y(“13”,10,2)mustreturn“1101”.Yourmethodmustworkforthesamerangeof
basesasinquestion1.
Basicidea:usethex2tenandten2xmethods.Here'sonepossiblesolution:
public String x2y(String input, int sourceBase, int destinationBase) {
return ten2x(x2ten(input,sourceBase),destinationBase);
}
Thelargestmethod
Defineamethodnamedlargestthatacceptsanarrayofintandreturnsthelargestvaluefromthe
array.
WelearnedhowtowriteamethodlikethisinCSE115.Here'saprettystandardapproach.(Note
thatweassumethearrayisneithernullnorempty.)
public int largest(int[] array) {
int answer = array[0];
for (int i=1; i<array.length; i++) {
if (array[i] > answer) {
answer = array[i];
}
}
return answer;
}
ReflectionsonWriteUp2
6
TheindexOfLargestmethod
DefineamethodnamedindexOfLargestthatacceptsanarrayofintandreturnstheindexofthe
largestvaluefromthearray.
Verysimilartothelargestmethod,exceptthatratherthankeeptrackofthelargestvaluewekeep
trackofthelocationofthelargestvalue.Againweassumethatthearrayisneithernullnorempty.
public int indexOfLargest(int[] array) {
int answer = 0;
for (int i=1; i<array.length; i++) {
if (array[i] > array[answer]) {
answer = i;
}
}
return answer;
}
ThecountAllmethod
DefineamethodnamedcountAllthatacceptsaStringasanargument.Themethodmustreturn
anarrayofintofsize27,suchthatthevalueinposition0isacountofthenumberof‘a’and‘A’
charactersintheinput,thevalueinposition1isacountofthenumberof‘b’and‘B’charactersin
theinput,…thevalueinposition25isacountofthenumberof‘z’and‘Z’charactersintheinput,
andthevalueinposition26isacountofallthenon-alphabeticcharactersintheinput.For
example,
• ifsis"",thenallentriesinthearraymustbe0.
• ifsis"a",thenallentriesinthearraymustbe0exceptforentry0,whichmustbe1.
• ifsis"Baaa!",thenallentriesinthearraymustbe0exceptfor:
o entry0,whichmustbe3,
o entry1,whichmustbe1,and
o entry26,whichmustbe1.
TheonlymethodsyoumaycallontheStringsarecharAt(int)andlength().Youmayusethestatic
toLowerCasemethoddefinedintheCharacterclass,whichmapsachartoitslower-case
equivalent.Forexample,
• Character.toLowerCase('a')returns'a'
• Character.toLowerCase('A')returns'a'
• Character.toLowerCase('%')returns'%'
ForthismethodweagainneedtoprocesseverycharacterfromaString,soweshouldrecognizethe
generalsolutionpattern:
public TYPE solution(String input) {
TYPE answer = ...initial value... ;
for (int i=0; i<input.length(); i++) {
char ch = input.charAt(i);
...do something with ch...
}
return answer;
}
ReflectionsonWriteUp2
7
WeusetheCharacter.toLowerCasemethodtoavoidhavingtomakedistinctionsinsubsequentcode
betweenUPPERCASEandlowercasecharacters.Wewantalsotoleveragethefactthatwecando
chararithmeticinwritingacompactsolution,soweindexintotheanswerarraywiththech-'a'
expression.Here'sapossiblesolution:
public int[] countAll(String input) {
int[] answer = new int[27];
for (int i=0; i<input.length(); i++) {
char ch = Character.toLowerCase(input.charAt(i));
if ('a' <= ch && ch <= 'z') {
answer[ch-'a']++;
}
else {
answer[26]++;
}
}
return answer;
}
(Exerciseidea:gobackoverearliersolutionsandhighlightinbluethefairlyboilerplatecodethat
repeatsfromoneproblemtothenext.)
Download