Circular shift string
$begingroup$
So,basically I am working on an algorithm for circular shifting a string upto a position.There are two parameters required here.
- String of text to shift
- Number of shifts required.
For example:
Given string: "Hello"
Shifts: 3
Final: "ollHe"
Ignore the limited validation here.
import java.lang.*;
import java.util.*;
public class Shift
{
public String shifting(String s,Integer sh)
{
Integer shifts=sh;
String string=s;
char shifted=new char[50];
Integer pos=0;
for(int i=string.length();i>shifts;i--)
{
System.out.println(""+i);
pos++;
shifted[pos]=string.charAt(i-1);
}
System.out.println("Shifting complete");
for(int j=0;j<shifts;j++)
{
System.out.println(""+j);
pos++;
shifted[pos]=string.charAt(j);
}
return new String(shifted);
}
public static void main(String args) {
System.out.println("Enter the string ");
Scanner sc=new Scanner(System.in);
String string=sc.nextLine();
System.out.println("So you have entered:"+string);
System.out.println("Enter the number of shifts:");
Integer shifts=sc.nextInt();
System.out.println("number of shifts is:"+shifts.toString());
System.out.println("Shifted string:"+new Shift().shifting(string,shifts));
}
}
`
Give your views on the code here.
java algorithm stack
$endgroup$
|
show 2 more comments
$begingroup$
So,basically I am working on an algorithm for circular shifting a string upto a position.There are two parameters required here.
- String of text to shift
- Number of shifts required.
For example:
Given string: "Hello"
Shifts: 3
Final: "ollHe"
Ignore the limited validation here.
import java.lang.*;
import java.util.*;
public class Shift
{
public String shifting(String s,Integer sh)
{
Integer shifts=sh;
String string=s;
char shifted=new char[50];
Integer pos=0;
for(int i=string.length();i>shifts;i--)
{
System.out.println(""+i);
pos++;
shifted[pos]=string.charAt(i-1);
}
System.out.println("Shifting complete");
for(int j=0;j<shifts;j++)
{
System.out.println(""+j);
pos++;
shifted[pos]=string.charAt(j);
}
return new String(shifted);
}
public static void main(String args) {
System.out.println("Enter the string ");
Scanner sc=new Scanner(System.in);
String string=sc.nextLine();
System.out.println("So you have entered:"+string);
System.out.println("Enter the number of shifts:");
Integer shifts=sc.nextInt();
System.out.println("number of shifts is:"+shifts.toString());
System.out.println("Shifted string:"+new Shift().shifting(string,shifts));
}
}
`
Give your views on the code here.
java algorithm stack
$endgroup$
2
$begingroup$
assuming that the String is at most 50 characters is dangerous.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
$begingroup$
You should add an example to your question.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
1
$begingroup$
(The example still looks off in rev. 3: how did theo
andll
swap places?) What aboutstring.substring(shifts) + string.substring(0, shifts)
?
$endgroup$
– greybeard
Dec 13 '16 at 14:04
$begingroup$
("backticks" are for inline code snippets; there is a {}-button and a keyboard shortcut (<Ctrl>+k
) in the edit-window to turn the selection into a code block (prefixing every line with four additional spaces if the selection doesn't already look like this (then it removes four spaces from the start of every line).))
$endgroup$
– greybeard
Dec 13 '16 at 21:45
$begingroup$
@greybeard..You are right.I was using the wrong way to do it.Hello->oHell->loHel->lloHe.Can you suggest the correct way?
$endgroup$
– Javasamurai
Dec 14 '16 at 6:29
|
show 2 more comments
$begingroup$
So,basically I am working on an algorithm for circular shifting a string upto a position.There are two parameters required here.
- String of text to shift
- Number of shifts required.
For example:
Given string: "Hello"
Shifts: 3
Final: "ollHe"
Ignore the limited validation here.
import java.lang.*;
import java.util.*;
public class Shift
{
public String shifting(String s,Integer sh)
{
Integer shifts=sh;
String string=s;
char shifted=new char[50];
Integer pos=0;
for(int i=string.length();i>shifts;i--)
{
System.out.println(""+i);
pos++;
shifted[pos]=string.charAt(i-1);
}
System.out.println("Shifting complete");
for(int j=0;j<shifts;j++)
{
System.out.println(""+j);
pos++;
shifted[pos]=string.charAt(j);
}
return new String(shifted);
}
public static void main(String args) {
System.out.println("Enter the string ");
Scanner sc=new Scanner(System.in);
String string=sc.nextLine();
System.out.println("So you have entered:"+string);
System.out.println("Enter the number of shifts:");
Integer shifts=sc.nextInt();
System.out.println("number of shifts is:"+shifts.toString());
System.out.println("Shifted string:"+new Shift().shifting(string,shifts));
}
}
`
Give your views on the code here.
java algorithm stack
$endgroup$
So,basically I am working on an algorithm for circular shifting a string upto a position.There are two parameters required here.
- String of text to shift
- Number of shifts required.
For example:
Given string: "Hello"
Shifts: 3
Final: "ollHe"
Ignore the limited validation here.
import java.lang.*;
import java.util.*;
public class Shift
{
public String shifting(String s,Integer sh)
{
Integer shifts=sh;
String string=s;
char shifted=new char[50];
Integer pos=0;
for(int i=string.length();i>shifts;i--)
{
System.out.println(""+i);
pos++;
shifted[pos]=string.charAt(i-1);
}
System.out.println("Shifting complete");
for(int j=0;j<shifts;j++)
{
System.out.println(""+j);
pos++;
shifted[pos]=string.charAt(j);
}
return new String(shifted);
}
public static void main(String args) {
System.out.println("Enter the string ");
Scanner sc=new Scanner(System.in);
String string=sc.nextLine();
System.out.println("So you have entered:"+string);
System.out.println("Enter the number of shifts:");
Integer shifts=sc.nextInt();
System.out.println("number of shifts is:"+shifts.toString());
System.out.println("Shifted string:"+new Shift().shifting(string,shifts));
}
}
`
Give your views on the code here.
java algorithm stack
java algorithm stack
edited Dec 14 '16 at 6:31
Javasamurai
asked Dec 13 '16 at 12:38
JavasamuraiJavasamurai
11915
11915
2
$begingroup$
assuming that the String is at most 50 characters is dangerous.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
$begingroup$
You should add an example to your question.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
1
$begingroup$
(The example still looks off in rev. 3: how did theo
andll
swap places?) What aboutstring.substring(shifts) + string.substring(0, shifts)
?
$endgroup$
– greybeard
Dec 13 '16 at 14:04
$begingroup$
("backticks" are for inline code snippets; there is a {}-button and a keyboard shortcut (<Ctrl>+k
) in the edit-window to turn the selection into a code block (prefixing every line with four additional spaces if the selection doesn't already look like this (then it removes four spaces from the start of every line).))
$endgroup$
– greybeard
Dec 13 '16 at 21:45
$begingroup$
@greybeard..You are right.I was using the wrong way to do it.Hello->oHell->loHel->lloHe.Can you suggest the correct way?
$endgroup$
– Javasamurai
Dec 14 '16 at 6:29
|
show 2 more comments
2
$begingroup$
assuming that the String is at most 50 characters is dangerous.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
$begingroup$
You should add an example to your question.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
1
$begingroup$
(The example still looks off in rev. 3: how did theo
andll
swap places?) What aboutstring.substring(shifts) + string.substring(0, shifts)
?
$endgroup$
– greybeard
Dec 13 '16 at 14:04
$begingroup$
("backticks" are for inline code snippets; there is a {}-button and a keyboard shortcut (<Ctrl>+k
) in the edit-window to turn the selection into a code block (prefixing every line with four additional spaces if the selection doesn't already look like this (then it removes four spaces from the start of every line).))
$endgroup$
– greybeard
Dec 13 '16 at 21:45
$begingroup$
@greybeard..You are right.I was using the wrong way to do it.Hello->oHell->loHel->lloHe.Can you suggest the correct way?
$endgroup$
– Javasamurai
Dec 14 '16 at 6:29
2
2
$begingroup$
assuming that the String is at most 50 characters is dangerous.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
$begingroup$
assuming that the String is at most 50 characters is dangerous.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
$begingroup$
You should add an example to your question.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
$begingroup$
You should add an example to your question.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
1
1
$begingroup$
(The example still looks off in rev. 3: how did the
o
and ll
swap places?) What about string.substring(shifts) + string.substring(0, shifts)
?$endgroup$
– greybeard
Dec 13 '16 at 14:04
$begingroup$
(The example still looks off in rev. 3: how did the
o
and ll
swap places?) What about string.substring(shifts) + string.substring(0, shifts)
?$endgroup$
– greybeard
Dec 13 '16 at 14:04
$begingroup$
("backticks" are for inline code snippets; there is a {}-button and a keyboard shortcut (
<Ctrl>+k
) in the edit-window to turn the selection into a code block (prefixing every line with four additional spaces if the selection doesn't already look like this (then it removes four spaces from the start of every line).))$endgroup$
– greybeard
Dec 13 '16 at 21:45
$begingroup$
("backticks" are for inline code snippets; there is a {}-button and a keyboard shortcut (
<Ctrl>+k
) in the edit-window to turn the selection into a code block (prefixing every line with four additional spaces if the selection doesn't already look like this (then it removes four spaces from the start of every line).))$endgroup$
– greybeard
Dec 13 '16 at 21:45
$begingroup$
@greybeard..You are right.I was using the wrong way to do it.Hello->oHell->loHel->lloHe.Can you suggest the correct way?
$endgroup$
– Javasamurai
Dec 14 '16 at 6:29
$begingroup$
@greybeard..You are right.I was using the wrong way to do it.Hello->oHell->loHel->lloHe.Can you suggest the correct way?
$endgroup$
– Javasamurai
Dec 14 '16 at 6:29
|
show 2 more comments
4 Answers
4
active
oldest
votes
$begingroup$
Do you have any constraints?
- Is your example wrong? I would expected
lloHe
- If you are concerned of modifying your method parameters make them
final
. Copy it to local variables and don't change the variables is kind of useless. - Don't use short variables names (exception: the loop counter)
- If you use
Integer
instead ofint
, you should handlenull
- Maybe a simple
static
utility method would be fine here, except you have some inheritance scenario in mind. - Maybe you should also indicate that you are shifting left for positive numbers
- You should take the length of you string for the
char
.
Assuming your example is wrong, what about:
import java.util.Objects;
import javax.annotation.Nonnull;
public final class Shift
{
@Nonnull
public static String left( @Nonnull final String string, final int shift )
{
final int length = string.length();
if( length == 0 ) return "";
final int offset = ((shift % length) + length) % length; // get a positive offset
return string.substring( offset, length ) + string.substring( 0, offset );
}
public static void main( String... args )
{
assertEquals( "loHel", Shift.left( "Hello", -2 ) );
assertEquals( "oHell", Shift.left( "Hello", -1 ) );
assertEquals( "Hello", Shift.left( "Hello", 0 ) );
assertEquals( "elloH", Shift.left( "Hello", 1 ) );
assertEquals( "lloHe", Shift.left( "Hello", 2 ) );
assertEquals( "loHel", Shift.left( "Hello", 3 ) );
assertEquals( "oHell", Shift.left( "Hello", 4 ) );
assertEquals( "Hello", Shift.left( "Hello", 5 ) );
assertEquals( "elloH", Shift.left( "Hello", 6 ) );
assertEquals( "", Shift.left( "", 3 ) );
}
private static void assertEquals( String expected, String actual )
{
if( !Objects.equals( expected, actual ) ) throw new AssertionError( "Expected: >" + expected + "< was: >" + actual + "<" );
}
}
$endgroup$
$begingroup$
Needs to takeshift
modulostring.length()
, but otherwise this is the obvious way to do it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:00
$begingroup$
@PeterTaylor It's not that simple. I completed the validation and added some tests. Keep in mind that%
in java is the remainder and may become negative.
$endgroup$
– mheinzerling
Dec 14 '16 at 5:54
$begingroup$
Yes, that's the reason I used the word "modulo" rather than the symbol%
.
$endgroup$
– Peter Taylor
Dec 14 '16 at 8:19
add a comment |
$begingroup$
("Rotation" = "shift".)
You can perform any rotation in constant time by devising a String
wrapper that maintains the string itself and the index into that string which is to be considered as the head character of a rotation. Now, in order to rotate $k$ characters, just add $k$ to that internal offset and take the modulo of string length.
If you want to get a String
out of that wrapper, just call its toString()
. There is, however, an optimization: if the state of the wrapper is not "dirty", it returns the previous cached rotation. Otherwise, a new string will be created and the state marked as not dirty.
I had this in mind:
import java.util.Objects;
public class StringRotation {
private final String string;
private int headIndex;
private boolean dirty;
private String lastCreatedString;
public StringRotation(String string) {
this.string = Objects.requireNonNull(string,
"The input string is null.");
this.dirty = true;
}
public StringRotation rotate(int rotationCount) {
headIndex = mod(headIndex + rotationCount, string.length());
dirty = true;
return this;
}
public char charAt(int index) {
checkIndexWithinBounds(index);
return string.charAt(mod(headIndex + index, string.length()));
}
@Override
public String toString() {
if (!dirty) {
return lastCreatedString;
}
int stringLength = string.length();
StringBuilder sb = new StringBuilder(stringLength);
for (int i = 0; i < stringLength; ++i) {
sb.append(charAt(i));
}
dirty = false;
lastCreatedString = sb.toString();
return lastCreatedString;
}
private void checkIndexWithinBounds(int index) {
int stringLength = string.length();
if (index < 0) {
throw new IndexOutOfBoundsException(
"The character index is negative: " + index);
}
if (index >= stringLength) {
throw new IndexOutOfBoundsException(
"The character index is too large: " + index +
". The length of this string is " + stringLength);
}
}
private static int mod(int a, int q) {
int ret = a % q;
return ret < 0 ? ret + q : ret;
}
public static void main(String args) {
for (int i = 0; i < 10; ++i) {
System.out.println(new StringRotation("hello").rotate(i));
}
System.out.println("---");
for (int i = 0; i > -10; --i) {
System.out.println(new StringRotation("hello").rotate(i));
}
}
}
$endgroup$
$begingroup$
Maybe a little over-engineered without further requirements :)
$endgroup$
– mheinzerling
Dec 13 '16 at 13:14
1
$begingroup$
(Pity you can'textends java.lang.String
.)
$endgroup$
– greybeard
Dec 13 '16 at 13:59
$begingroup$
@greybeard, but it is possible to implementCharSequence
, and a wrapper approach should consider it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 14:59
$begingroup$
@PeterTaylor Perhaps. YetCharSequence
does not provide rotation methods, so using them would requireStringRotation
after all.
$endgroup$
– coderodde
Dec 13 '16 at 15:04
$begingroup$
Maybe I didn't express myself clearly enough. I was suggesting that a production version ofStringRotation
should implementCharSequence
. (To be honest, if I went down the wrapper route then I would make the wrapper immutable with constructorStringRotation(CharSequence, int)
).
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:41
add a comment |
$begingroup$
In my opinion this is way better by a landslide:
import java.util.Scanner;
public class Example {
static String shifter(String stringToShift, int numberOfShifts){
for(int i = 0; i < numberOfShifts;i++)
{
// Store the character you want to shift
char temporaryChar = stringToShift.charAt(stringToShift.length() - 1);
// Store the character with the original String. Character first
stringToShift = temporaryChar + stringToShift;
// Now that we did that, the string is 1 character longer so we need to take a substring of it
stringToShift = stringToShift.substring(0, stringToShift.length()-1);
}
// After everything is done return the String
return stringToShift;
}
public static void main(String args) {
// Start getting input
Scanner input = new Scanner(System.in);
// Get String input
System.out.println("Enter the string ");
String answer = input.nextLine();
System.out.println("So you have entered: " + answer);
// Get int input
System.out.println("Enter the number of shifts:");
int numberOfShifts = input.nextInt();
System.out.println("number of shifts is: " + numberOfShifts);
// Shift and print out the answer
System.out.println("Shifted string: " + shifter(answer, numberOfShifts));
// Close input after you're done
input.close();
}
}
Pay attention at my style of coding and naming, it's better to have longer names so later you at least understand why the variable is there in the first place.
$endgroup$
1
$begingroup$
This takes timeOmega(mn)
wherem
is the displacement of the shift andn
is the length of the string. It's possible to do it inO(n)
.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:03
$begingroup$
I just wrote how to write better, more understandable code rather than efficient
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 15:18
$begingroup$
I disagree that it's better to replace a linear algorithm with a quadratic one unless you're massively reducing the constant factor. I'm not really convinced that this code is more understandable either. I can't understand the indexing inchar temporaryChar = stringToShift.charAt(stringToShift.length()- i - 1);
: it looks buggy and a quick test seems to support that.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:50
$begingroup$
oh sorry didn't notice that, i'll fix that quick
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 18:33
$begingroup$
I have to agree with @PeterTaylor. When you start writing you own code instead of using the libraries, you should get faster and not slower, especial if it get harder to read your code in the end.
$endgroup$
– mheinzerling
Dec 14 '16 at 6:07
|
show 1 more comment
$begingroup$
fun getShiftedString(s: String, leftShifts: Int, rightShifts: Int): String {
val shift = leftShifts - rightShifts
return when (shift) {
0 -> s
else -> {
val strBuilder = StringBuilder(s)
s.indices.forEach { index ->
val newShift = if (shift > 0) s.length - shift else -shift
val newIndex = (index + newShift).absoluteValue % s.length
strBuilder[newIndex] = s[index]
}
strBuilder.toString()
}
}
}
New contributor
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f149749%2fcircular-shift-string%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Do you have any constraints?
- Is your example wrong? I would expected
lloHe
- If you are concerned of modifying your method parameters make them
final
. Copy it to local variables and don't change the variables is kind of useless. - Don't use short variables names (exception: the loop counter)
- If you use
Integer
instead ofint
, you should handlenull
- Maybe a simple
static
utility method would be fine here, except you have some inheritance scenario in mind. - Maybe you should also indicate that you are shifting left for positive numbers
- You should take the length of you string for the
char
.
Assuming your example is wrong, what about:
import java.util.Objects;
import javax.annotation.Nonnull;
public final class Shift
{
@Nonnull
public static String left( @Nonnull final String string, final int shift )
{
final int length = string.length();
if( length == 0 ) return "";
final int offset = ((shift % length) + length) % length; // get a positive offset
return string.substring( offset, length ) + string.substring( 0, offset );
}
public static void main( String... args )
{
assertEquals( "loHel", Shift.left( "Hello", -2 ) );
assertEquals( "oHell", Shift.left( "Hello", -1 ) );
assertEquals( "Hello", Shift.left( "Hello", 0 ) );
assertEquals( "elloH", Shift.left( "Hello", 1 ) );
assertEquals( "lloHe", Shift.left( "Hello", 2 ) );
assertEquals( "loHel", Shift.left( "Hello", 3 ) );
assertEquals( "oHell", Shift.left( "Hello", 4 ) );
assertEquals( "Hello", Shift.left( "Hello", 5 ) );
assertEquals( "elloH", Shift.left( "Hello", 6 ) );
assertEquals( "", Shift.left( "", 3 ) );
}
private static void assertEquals( String expected, String actual )
{
if( !Objects.equals( expected, actual ) ) throw new AssertionError( "Expected: >" + expected + "< was: >" + actual + "<" );
}
}
$endgroup$
$begingroup$
Needs to takeshift
modulostring.length()
, but otherwise this is the obvious way to do it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:00
$begingroup$
@PeterTaylor It's not that simple. I completed the validation and added some tests. Keep in mind that%
in java is the remainder and may become negative.
$endgroup$
– mheinzerling
Dec 14 '16 at 5:54
$begingroup$
Yes, that's the reason I used the word "modulo" rather than the symbol%
.
$endgroup$
– Peter Taylor
Dec 14 '16 at 8:19
add a comment |
$begingroup$
Do you have any constraints?
- Is your example wrong? I would expected
lloHe
- If you are concerned of modifying your method parameters make them
final
. Copy it to local variables and don't change the variables is kind of useless. - Don't use short variables names (exception: the loop counter)
- If you use
Integer
instead ofint
, you should handlenull
- Maybe a simple
static
utility method would be fine here, except you have some inheritance scenario in mind. - Maybe you should also indicate that you are shifting left for positive numbers
- You should take the length of you string for the
char
.
Assuming your example is wrong, what about:
import java.util.Objects;
import javax.annotation.Nonnull;
public final class Shift
{
@Nonnull
public static String left( @Nonnull final String string, final int shift )
{
final int length = string.length();
if( length == 0 ) return "";
final int offset = ((shift % length) + length) % length; // get a positive offset
return string.substring( offset, length ) + string.substring( 0, offset );
}
public static void main( String... args )
{
assertEquals( "loHel", Shift.left( "Hello", -2 ) );
assertEquals( "oHell", Shift.left( "Hello", -1 ) );
assertEquals( "Hello", Shift.left( "Hello", 0 ) );
assertEquals( "elloH", Shift.left( "Hello", 1 ) );
assertEquals( "lloHe", Shift.left( "Hello", 2 ) );
assertEquals( "loHel", Shift.left( "Hello", 3 ) );
assertEquals( "oHell", Shift.left( "Hello", 4 ) );
assertEquals( "Hello", Shift.left( "Hello", 5 ) );
assertEquals( "elloH", Shift.left( "Hello", 6 ) );
assertEquals( "", Shift.left( "", 3 ) );
}
private static void assertEquals( String expected, String actual )
{
if( !Objects.equals( expected, actual ) ) throw new AssertionError( "Expected: >" + expected + "< was: >" + actual + "<" );
}
}
$endgroup$
$begingroup$
Needs to takeshift
modulostring.length()
, but otherwise this is the obvious way to do it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:00
$begingroup$
@PeterTaylor It's not that simple. I completed the validation and added some tests. Keep in mind that%
in java is the remainder and may become negative.
$endgroup$
– mheinzerling
Dec 14 '16 at 5:54
$begingroup$
Yes, that's the reason I used the word "modulo" rather than the symbol%
.
$endgroup$
– Peter Taylor
Dec 14 '16 at 8:19
add a comment |
$begingroup$
Do you have any constraints?
- Is your example wrong? I would expected
lloHe
- If you are concerned of modifying your method parameters make them
final
. Copy it to local variables and don't change the variables is kind of useless. - Don't use short variables names (exception: the loop counter)
- If you use
Integer
instead ofint
, you should handlenull
- Maybe a simple
static
utility method would be fine here, except you have some inheritance scenario in mind. - Maybe you should also indicate that you are shifting left for positive numbers
- You should take the length of you string for the
char
.
Assuming your example is wrong, what about:
import java.util.Objects;
import javax.annotation.Nonnull;
public final class Shift
{
@Nonnull
public static String left( @Nonnull final String string, final int shift )
{
final int length = string.length();
if( length == 0 ) return "";
final int offset = ((shift % length) + length) % length; // get a positive offset
return string.substring( offset, length ) + string.substring( 0, offset );
}
public static void main( String... args )
{
assertEquals( "loHel", Shift.left( "Hello", -2 ) );
assertEquals( "oHell", Shift.left( "Hello", -1 ) );
assertEquals( "Hello", Shift.left( "Hello", 0 ) );
assertEquals( "elloH", Shift.left( "Hello", 1 ) );
assertEquals( "lloHe", Shift.left( "Hello", 2 ) );
assertEquals( "loHel", Shift.left( "Hello", 3 ) );
assertEquals( "oHell", Shift.left( "Hello", 4 ) );
assertEquals( "Hello", Shift.left( "Hello", 5 ) );
assertEquals( "elloH", Shift.left( "Hello", 6 ) );
assertEquals( "", Shift.left( "", 3 ) );
}
private static void assertEquals( String expected, String actual )
{
if( !Objects.equals( expected, actual ) ) throw new AssertionError( "Expected: >" + expected + "< was: >" + actual + "<" );
}
}
$endgroup$
Do you have any constraints?
- Is your example wrong? I would expected
lloHe
- If you are concerned of modifying your method parameters make them
final
. Copy it to local variables and don't change the variables is kind of useless. - Don't use short variables names (exception: the loop counter)
- If you use
Integer
instead ofint
, you should handlenull
- Maybe a simple
static
utility method would be fine here, except you have some inheritance scenario in mind. - Maybe you should also indicate that you are shifting left for positive numbers
- You should take the length of you string for the
char
.
Assuming your example is wrong, what about:
import java.util.Objects;
import javax.annotation.Nonnull;
public final class Shift
{
@Nonnull
public static String left( @Nonnull final String string, final int shift )
{
final int length = string.length();
if( length == 0 ) return "";
final int offset = ((shift % length) + length) % length; // get a positive offset
return string.substring( offset, length ) + string.substring( 0, offset );
}
public static void main( String... args )
{
assertEquals( "loHel", Shift.left( "Hello", -2 ) );
assertEquals( "oHell", Shift.left( "Hello", -1 ) );
assertEquals( "Hello", Shift.left( "Hello", 0 ) );
assertEquals( "elloH", Shift.left( "Hello", 1 ) );
assertEquals( "lloHe", Shift.left( "Hello", 2 ) );
assertEquals( "loHel", Shift.left( "Hello", 3 ) );
assertEquals( "oHell", Shift.left( "Hello", 4 ) );
assertEquals( "Hello", Shift.left( "Hello", 5 ) );
assertEquals( "elloH", Shift.left( "Hello", 6 ) );
assertEquals( "", Shift.left( "", 3 ) );
}
private static void assertEquals( String expected, String actual )
{
if( !Objects.equals( expected, actual ) ) throw new AssertionError( "Expected: >" + expected + "< was: >" + actual + "<" );
}
}
edited Dec 14 '16 at 6:10
answered Dec 13 '16 at 12:59
mheinzerlingmheinzerling
2,644917
2,644917
$begingroup$
Needs to takeshift
modulostring.length()
, but otherwise this is the obvious way to do it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:00
$begingroup$
@PeterTaylor It's not that simple. I completed the validation and added some tests. Keep in mind that%
in java is the remainder and may become negative.
$endgroup$
– mheinzerling
Dec 14 '16 at 5:54
$begingroup$
Yes, that's the reason I used the word "modulo" rather than the symbol%
.
$endgroup$
– Peter Taylor
Dec 14 '16 at 8:19
add a comment |
$begingroup$
Needs to takeshift
modulostring.length()
, but otherwise this is the obvious way to do it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:00
$begingroup$
@PeterTaylor It's not that simple. I completed the validation and added some tests. Keep in mind that%
in java is the remainder and may become negative.
$endgroup$
– mheinzerling
Dec 14 '16 at 5:54
$begingroup$
Yes, that's the reason I used the word "modulo" rather than the symbol%
.
$endgroup$
– Peter Taylor
Dec 14 '16 at 8:19
$begingroup$
Needs to take
shift
modulo string.length()
, but otherwise this is the obvious way to do it.$endgroup$
– Peter Taylor
Dec 13 '16 at 15:00
$begingroup$
Needs to take
shift
modulo string.length()
, but otherwise this is the obvious way to do it.$endgroup$
– Peter Taylor
Dec 13 '16 at 15:00
$begingroup$
@PeterTaylor It's not that simple. I completed the validation and added some tests. Keep in mind that
%
in java is the remainder and may become negative.$endgroup$
– mheinzerling
Dec 14 '16 at 5:54
$begingroup$
@PeterTaylor It's not that simple. I completed the validation and added some tests. Keep in mind that
%
in java is the remainder and may become negative.$endgroup$
– mheinzerling
Dec 14 '16 at 5:54
$begingroup$
Yes, that's the reason I used the word "modulo" rather than the symbol
%
.$endgroup$
– Peter Taylor
Dec 14 '16 at 8:19
$begingroup$
Yes, that's the reason I used the word "modulo" rather than the symbol
%
.$endgroup$
– Peter Taylor
Dec 14 '16 at 8:19
add a comment |
$begingroup$
("Rotation" = "shift".)
You can perform any rotation in constant time by devising a String
wrapper that maintains the string itself and the index into that string which is to be considered as the head character of a rotation. Now, in order to rotate $k$ characters, just add $k$ to that internal offset and take the modulo of string length.
If you want to get a String
out of that wrapper, just call its toString()
. There is, however, an optimization: if the state of the wrapper is not "dirty", it returns the previous cached rotation. Otherwise, a new string will be created and the state marked as not dirty.
I had this in mind:
import java.util.Objects;
public class StringRotation {
private final String string;
private int headIndex;
private boolean dirty;
private String lastCreatedString;
public StringRotation(String string) {
this.string = Objects.requireNonNull(string,
"The input string is null.");
this.dirty = true;
}
public StringRotation rotate(int rotationCount) {
headIndex = mod(headIndex + rotationCount, string.length());
dirty = true;
return this;
}
public char charAt(int index) {
checkIndexWithinBounds(index);
return string.charAt(mod(headIndex + index, string.length()));
}
@Override
public String toString() {
if (!dirty) {
return lastCreatedString;
}
int stringLength = string.length();
StringBuilder sb = new StringBuilder(stringLength);
for (int i = 0; i < stringLength; ++i) {
sb.append(charAt(i));
}
dirty = false;
lastCreatedString = sb.toString();
return lastCreatedString;
}
private void checkIndexWithinBounds(int index) {
int stringLength = string.length();
if (index < 0) {
throw new IndexOutOfBoundsException(
"The character index is negative: " + index);
}
if (index >= stringLength) {
throw new IndexOutOfBoundsException(
"The character index is too large: " + index +
". The length of this string is " + stringLength);
}
}
private static int mod(int a, int q) {
int ret = a % q;
return ret < 0 ? ret + q : ret;
}
public static void main(String args) {
for (int i = 0; i < 10; ++i) {
System.out.println(new StringRotation("hello").rotate(i));
}
System.out.println("---");
for (int i = 0; i > -10; --i) {
System.out.println(new StringRotation("hello").rotate(i));
}
}
}
$endgroup$
$begingroup$
Maybe a little over-engineered without further requirements :)
$endgroup$
– mheinzerling
Dec 13 '16 at 13:14
1
$begingroup$
(Pity you can'textends java.lang.String
.)
$endgroup$
– greybeard
Dec 13 '16 at 13:59
$begingroup$
@greybeard, but it is possible to implementCharSequence
, and a wrapper approach should consider it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 14:59
$begingroup$
@PeterTaylor Perhaps. YetCharSequence
does not provide rotation methods, so using them would requireStringRotation
after all.
$endgroup$
– coderodde
Dec 13 '16 at 15:04
$begingroup$
Maybe I didn't express myself clearly enough. I was suggesting that a production version ofStringRotation
should implementCharSequence
. (To be honest, if I went down the wrapper route then I would make the wrapper immutable with constructorStringRotation(CharSequence, int)
).
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:41
add a comment |
$begingroup$
("Rotation" = "shift".)
You can perform any rotation in constant time by devising a String
wrapper that maintains the string itself and the index into that string which is to be considered as the head character of a rotation. Now, in order to rotate $k$ characters, just add $k$ to that internal offset and take the modulo of string length.
If you want to get a String
out of that wrapper, just call its toString()
. There is, however, an optimization: if the state of the wrapper is not "dirty", it returns the previous cached rotation. Otherwise, a new string will be created and the state marked as not dirty.
I had this in mind:
import java.util.Objects;
public class StringRotation {
private final String string;
private int headIndex;
private boolean dirty;
private String lastCreatedString;
public StringRotation(String string) {
this.string = Objects.requireNonNull(string,
"The input string is null.");
this.dirty = true;
}
public StringRotation rotate(int rotationCount) {
headIndex = mod(headIndex + rotationCount, string.length());
dirty = true;
return this;
}
public char charAt(int index) {
checkIndexWithinBounds(index);
return string.charAt(mod(headIndex + index, string.length()));
}
@Override
public String toString() {
if (!dirty) {
return lastCreatedString;
}
int stringLength = string.length();
StringBuilder sb = new StringBuilder(stringLength);
for (int i = 0; i < stringLength; ++i) {
sb.append(charAt(i));
}
dirty = false;
lastCreatedString = sb.toString();
return lastCreatedString;
}
private void checkIndexWithinBounds(int index) {
int stringLength = string.length();
if (index < 0) {
throw new IndexOutOfBoundsException(
"The character index is negative: " + index);
}
if (index >= stringLength) {
throw new IndexOutOfBoundsException(
"The character index is too large: " + index +
". The length of this string is " + stringLength);
}
}
private static int mod(int a, int q) {
int ret = a % q;
return ret < 0 ? ret + q : ret;
}
public static void main(String args) {
for (int i = 0; i < 10; ++i) {
System.out.println(new StringRotation("hello").rotate(i));
}
System.out.println("---");
for (int i = 0; i > -10; --i) {
System.out.println(new StringRotation("hello").rotate(i));
}
}
}
$endgroup$
$begingroup$
Maybe a little over-engineered without further requirements :)
$endgroup$
– mheinzerling
Dec 13 '16 at 13:14
1
$begingroup$
(Pity you can'textends java.lang.String
.)
$endgroup$
– greybeard
Dec 13 '16 at 13:59
$begingroup$
@greybeard, but it is possible to implementCharSequence
, and a wrapper approach should consider it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 14:59
$begingroup$
@PeterTaylor Perhaps. YetCharSequence
does not provide rotation methods, so using them would requireStringRotation
after all.
$endgroup$
– coderodde
Dec 13 '16 at 15:04
$begingroup$
Maybe I didn't express myself clearly enough. I was suggesting that a production version ofStringRotation
should implementCharSequence
. (To be honest, if I went down the wrapper route then I would make the wrapper immutable with constructorStringRotation(CharSequence, int)
).
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:41
add a comment |
$begingroup$
("Rotation" = "shift".)
You can perform any rotation in constant time by devising a String
wrapper that maintains the string itself and the index into that string which is to be considered as the head character of a rotation. Now, in order to rotate $k$ characters, just add $k$ to that internal offset and take the modulo of string length.
If you want to get a String
out of that wrapper, just call its toString()
. There is, however, an optimization: if the state of the wrapper is not "dirty", it returns the previous cached rotation. Otherwise, a new string will be created and the state marked as not dirty.
I had this in mind:
import java.util.Objects;
public class StringRotation {
private final String string;
private int headIndex;
private boolean dirty;
private String lastCreatedString;
public StringRotation(String string) {
this.string = Objects.requireNonNull(string,
"The input string is null.");
this.dirty = true;
}
public StringRotation rotate(int rotationCount) {
headIndex = mod(headIndex + rotationCount, string.length());
dirty = true;
return this;
}
public char charAt(int index) {
checkIndexWithinBounds(index);
return string.charAt(mod(headIndex + index, string.length()));
}
@Override
public String toString() {
if (!dirty) {
return lastCreatedString;
}
int stringLength = string.length();
StringBuilder sb = new StringBuilder(stringLength);
for (int i = 0; i < stringLength; ++i) {
sb.append(charAt(i));
}
dirty = false;
lastCreatedString = sb.toString();
return lastCreatedString;
}
private void checkIndexWithinBounds(int index) {
int stringLength = string.length();
if (index < 0) {
throw new IndexOutOfBoundsException(
"The character index is negative: " + index);
}
if (index >= stringLength) {
throw new IndexOutOfBoundsException(
"The character index is too large: " + index +
". The length of this string is " + stringLength);
}
}
private static int mod(int a, int q) {
int ret = a % q;
return ret < 0 ? ret + q : ret;
}
public static void main(String args) {
for (int i = 0; i < 10; ++i) {
System.out.println(new StringRotation("hello").rotate(i));
}
System.out.println("---");
for (int i = 0; i > -10; --i) {
System.out.println(new StringRotation("hello").rotate(i));
}
}
}
$endgroup$
("Rotation" = "shift".)
You can perform any rotation in constant time by devising a String
wrapper that maintains the string itself and the index into that string which is to be considered as the head character of a rotation. Now, in order to rotate $k$ characters, just add $k$ to that internal offset and take the modulo of string length.
If you want to get a String
out of that wrapper, just call its toString()
. There is, however, an optimization: if the state of the wrapper is not "dirty", it returns the previous cached rotation. Otherwise, a new string will be created and the state marked as not dirty.
I had this in mind:
import java.util.Objects;
public class StringRotation {
private final String string;
private int headIndex;
private boolean dirty;
private String lastCreatedString;
public StringRotation(String string) {
this.string = Objects.requireNonNull(string,
"The input string is null.");
this.dirty = true;
}
public StringRotation rotate(int rotationCount) {
headIndex = mod(headIndex + rotationCount, string.length());
dirty = true;
return this;
}
public char charAt(int index) {
checkIndexWithinBounds(index);
return string.charAt(mod(headIndex + index, string.length()));
}
@Override
public String toString() {
if (!dirty) {
return lastCreatedString;
}
int stringLength = string.length();
StringBuilder sb = new StringBuilder(stringLength);
for (int i = 0; i < stringLength; ++i) {
sb.append(charAt(i));
}
dirty = false;
lastCreatedString = sb.toString();
return lastCreatedString;
}
private void checkIndexWithinBounds(int index) {
int stringLength = string.length();
if (index < 0) {
throw new IndexOutOfBoundsException(
"The character index is negative: " + index);
}
if (index >= stringLength) {
throw new IndexOutOfBoundsException(
"The character index is too large: " + index +
". The length of this string is " + stringLength);
}
}
private static int mod(int a, int q) {
int ret = a % q;
return ret < 0 ? ret + q : ret;
}
public static void main(String args) {
for (int i = 0; i < 10; ++i) {
System.out.println(new StringRotation("hello").rotate(i));
}
System.out.println("---");
for (int i = 0; i > -10; --i) {
System.out.println(new StringRotation("hello").rotate(i));
}
}
}
answered Dec 13 '16 at 13:07
coderoddecoderodde
15.7k538127
15.7k538127
$begingroup$
Maybe a little over-engineered without further requirements :)
$endgroup$
– mheinzerling
Dec 13 '16 at 13:14
1
$begingroup$
(Pity you can'textends java.lang.String
.)
$endgroup$
– greybeard
Dec 13 '16 at 13:59
$begingroup$
@greybeard, but it is possible to implementCharSequence
, and a wrapper approach should consider it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 14:59
$begingroup$
@PeterTaylor Perhaps. YetCharSequence
does not provide rotation methods, so using them would requireStringRotation
after all.
$endgroup$
– coderodde
Dec 13 '16 at 15:04
$begingroup$
Maybe I didn't express myself clearly enough. I was suggesting that a production version ofStringRotation
should implementCharSequence
. (To be honest, if I went down the wrapper route then I would make the wrapper immutable with constructorStringRotation(CharSequence, int)
).
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:41
add a comment |
$begingroup$
Maybe a little over-engineered without further requirements :)
$endgroup$
– mheinzerling
Dec 13 '16 at 13:14
1
$begingroup$
(Pity you can'textends java.lang.String
.)
$endgroup$
– greybeard
Dec 13 '16 at 13:59
$begingroup$
@greybeard, but it is possible to implementCharSequence
, and a wrapper approach should consider it.
$endgroup$
– Peter Taylor
Dec 13 '16 at 14:59
$begingroup$
@PeterTaylor Perhaps. YetCharSequence
does not provide rotation methods, so using them would requireStringRotation
after all.
$endgroup$
– coderodde
Dec 13 '16 at 15:04
$begingroup$
Maybe I didn't express myself clearly enough. I was suggesting that a production version ofStringRotation
should implementCharSequence
. (To be honest, if I went down the wrapper route then I would make the wrapper immutable with constructorStringRotation(CharSequence, int)
).
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:41
$begingroup$
Maybe a little over-engineered without further requirements :)
$endgroup$
– mheinzerling
Dec 13 '16 at 13:14
$begingroup$
Maybe a little over-engineered without further requirements :)
$endgroup$
– mheinzerling
Dec 13 '16 at 13:14
1
1
$begingroup$
(Pity you can't
extends java.lang.String
.)$endgroup$
– greybeard
Dec 13 '16 at 13:59
$begingroup$
(Pity you can't
extends java.lang.String
.)$endgroup$
– greybeard
Dec 13 '16 at 13:59
$begingroup$
@greybeard, but it is possible to implement
CharSequence
, and a wrapper approach should consider it.$endgroup$
– Peter Taylor
Dec 13 '16 at 14:59
$begingroup$
@greybeard, but it is possible to implement
CharSequence
, and a wrapper approach should consider it.$endgroup$
– Peter Taylor
Dec 13 '16 at 14:59
$begingroup$
@PeterTaylor Perhaps. Yet
CharSequence
does not provide rotation methods, so using them would require StringRotation
after all.$endgroup$
– coderodde
Dec 13 '16 at 15:04
$begingroup$
@PeterTaylor Perhaps. Yet
CharSequence
does not provide rotation methods, so using them would require StringRotation
after all.$endgroup$
– coderodde
Dec 13 '16 at 15:04
$begingroup$
Maybe I didn't express myself clearly enough. I was suggesting that a production version of
StringRotation
should implement CharSequence
. (To be honest, if I went down the wrapper route then I would make the wrapper immutable with constructor StringRotation(CharSequence, int)
).$endgroup$
– Peter Taylor
Dec 13 '16 at 15:41
$begingroup$
Maybe I didn't express myself clearly enough. I was suggesting that a production version of
StringRotation
should implement CharSequence
. (To be honest, if I went down the wrapper route then I would make the wrapper immutable with constructor StringRotation(CharSequence, int)
).$endgroup$
– Peter Taylor
Dec 13 '16 at 15:41
add a comment |
$begingroup$
In my opinion this is way better by a landslide:
import java.util.Scanner;
public class Example {
static String shifter(String stringToShift, int numberOfShifts){
for(int i = 0; i < numberOfShifts;i++)
{
// Store the character you want to shift
char temporaryChar = stringToShift.charAt(stringToShift.length() - 1);
// Store the character with the original String. Character first
stringToShift = temporaryChar + stringToShift;
// Now that we did that, the string is 1 character longer so we need to take a substring of it
stringToShift = stringToShift.substring(0, stringToShift.length()-1);
}
// After everything is done return the String
return stringToShift;
}
public static void main(String args) {
// Start getting input
Scanner input = new Scanner(System.in);
// Get String input
System.out.println("Enter the string ");
String answer = input.nextLine();
System.out.println("So you have entered: " + answer);
// Get int input
System.out.println("Enter the number of shifts:");
int numberOfShifts = input.nextInt();
System.out.println("number of shifts is: " + numberOfShifts);
// Shift and print out the answer
System.out.println("Shifted string: " + shifter(answer, numberOfShifts));
// Close input after you're done
input.close();
}
}
Pay attention at my style of coding and naming, it's better to have longer names so later you at least understand why the variable is there in the first place.
$endgroup$
1
$begingroup$
This takes timeOmega(mn)
wherem
is the displacement of the shift andn
is the length of the string. It's possible to do it inO(n)
.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:03
$begingroup$
I just wrote how to write better, more understandable code rather than efficient
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 15:18
$begingroup$
I disagree that it's better to replace a linear algorithm with a quadratic one unless you're massively reducing the constant factor. I'm not really convinced that this code is more understandable either. I can't understand the indexing inchar temporaryChar = stringToShift.charAt(stringToShift.length()- i - 1);
: it looks buggy and a quick test seems to support that.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:50
$begingroup$
oh sorry didn't notice that, i'll fix that quick
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 18:33
$begingroup$
I have to agree with @PeterTaylor. When you start writing you own code instead of using the libraries, you should get faster and not slower, especial if it get harder to read your code in the end.
$endgroup$
– mheinzerling
Dec 14 '16 at 6:07
|
show 1 more comment
$begingroup$
In my opinion this is way better by a landslide:
import java.util.Scanner;
public class Example {
static String shifter(String stringToShift, int numberOfShifts){
for(int i = 0; i < numberOfShifts;i++)
{
// Store the character you want to shift
char temporaryChar = stringToShift.charAt(stringToShift.length() - 1);
// Store the character with the original String. Character first
stringToShift = temporaryChar + stringToShift;
// Now that we did that, the string is 1 character longer so we need to take a substring of it
stringToShift = stringToShift.substring(0, stringToShift.length()-1);
}
// After everything is done return the String
return stringToShift;
}
public static void main(String args) {
// Start getting input
Scanner input = new Scanner(System.in);
// Get String input
System.out.println("Enter the string ");
String answer = input.nextLine();
System.out.println("So you have entered: " + answer);
// Get int input
System.out.println("Enter the number of shifts:");
int numberOfShifts = input.nextInt();
System.out.println("number of shifts is: " + numberOfShifts);
// Shift and print out the answer
System.out.println("Shifted string: " + shifter(answer, numberOfShifts));
// Close input after you're done
input.close();
}
}
Pay attention at my style of coding and naming, it's better to have longer names so later you at least understand why the variable is there in the first place.
$endgroup$
1
$begingroup$
This takes timeOmega(mn)
wherem
is the displacement of the shift andn
is the length of the string. It's possible to do it inO(n)
.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:03
$begingroup$
I just wrote how to write better, more understandable code rather than efficient
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 15:18
$begingroup$
I disagree that it's better to replace a linear algorithm with a quadratic one unless you're massively reducing the constant factor. I'm not really convinced that this code is more understandable either. I can't understand the indexing inchar temporaryChar = stringToShift.charAt(stringToShift.length()- i - 1);
: it looks buggy and a quick test seems to support that.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:50
$begingroup$
oh sorry didn't notice that, i'll fix that quick
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 18:33
$begingroup$
I have to agree with @PeterTaylor. When you start writing you own code instead of using the libraries, you should get faster and not slower, especial if it get harder to read your code in the end.
$endgroup$
– mheinzerling
Dec 14 '16 at 6:07
|
show 1 more comment
$begingroup$
In my opinion this is way better by a landslide:
import java.util.Scanner;
public class Example {
static String shifter(String stringToShift, int numberOfShifts){
for(int i = 0; i < numberOfShifts;i++)
{
// Store the character you want to shift
char temporaryChar = stringToShift.charAt(stringToShift.length() - 1);
// Store the character with the original String. Character first
stringToShift = temporaryChar + stringToShift;
// Now that we did that, the string is 1 character longer so we need to take a substring of it
stringToShift = stringToShift.substring(0, stringToShift.length()-1);
}
// After everything is done return the String
return stringToShift;
}
public static void main(String args) {
// Start getting input
Scanner input = new Scanner(System.in);
// Get String input
System.out.println("Enter the string ");
String answer = input.nextLine();
System.out.println("So you have entered: " + answer);
// Get int input
System.out.println("Enter the number of shifts:");
int numberOfShifts = input.nextInt();
System.out.println("number of shifts is: " + numberOfShifts);
// Shift and print out the answer
System.out.println("Shifted string: " + shifter(answer, numberOfShifts));
// Close input after you're done
input.close();
}
}
Pay attention at my style of coding and naming, it's better to have longer names so later you at least understand why the variable is there in the first place.
$endgroup$
In my opinion this is way better by a landslide:
import java.util.Scanner;
public class Example {
static String shifter(String stringToShift, int numberOfShifts){
for(int i = 0; i < numberOfShifts;i++)
{
// Store the character you want to shift
char temporaryChar = stringToShift.charAt(stringToShift.length() - 1);
// Store the character with the original String. Character first
stringToShift = temporaryChar + stringToShift;
// Now that we did that, the string is 1 character longer so we need to take a substring of it
stringToShift = stringToShift.substring(0, stringToShift.length()-1);
}
// After everything is done return the String
return stringToShift;
}
public static void main(String args) {
// Start getting input
Scanner input = new Scanner(System.in);
// Get String input
System.out.println("Enter the string ");
String answer = input.nextLine();
System.out.println("So you have entered: " + answer);
// Get int input
System.out.println("Enter the number of shifts:");
int numberOfShifts = input.nextInt();
System.out.println("number of shifts is: " + numberOfShifts);
// Shift and print out the answer
System.out.println("Shifted string: " + shifter(answer, numberOfShifts));
// Close input after you're done
input.close();
}
}
Pay attention at my style of coding and naming, it's better to have longer names so later you at least understand why the variable is there in the first place.
edited Dec 13 '16 at 18:55
answered Dec 13 '16 at 13:49
Erlandas AksomaitisErlandas Aksomaitis
174
174
1
$begingroup$
This takes timeOmega(mn)
wherem
is the displacement of the shift andn
is the length of the string. It's possible to do it inO(n)
.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:03
$begingroup$
I just wrote how to write better, more understandable code rather than efficient
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 15:18
$begingroup$
I disagree that it's better to replace a linear algorithm with a quadratic one unless you're massively reducing the constant factor. I'm not really convinced that this code is more understandable either. I can't understand the indexing inchar temporaryChar = stringToShift.charAt(stringToShift.length()- i - 1);
: it looks buggy and a quick test seems to support that.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:50
$begingroup$
oh sorry didn't notice that, i'll fix that quick
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 18:33
$begingroup$
I have to agree with @PeterTaylor. When you start writing you own code instead of using the libraries, you should get faster and not slower, especial if it get harder to read your code in the end.
$endgroup$
– mheinzerling
Dec 14 '16 at 6:07
|
show 1 more comment
1
$begingroup$
This takes timeOmega(mn)
wherem
is the displacement of the shift andn
is the length of the string. It's possible to do it inO(n)
.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:03
$begingroup$
I just wrote how to write better, more understandable code rather than efficient
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 15:18
$begingroup$
I disagree that it's better to replace a linear algorithm with a quadratic one unless you're massively reducing the constant factor. I'm not really convinced that this code is more understandable either. I can't understand the indexing inchar temporaryChar = stringToShift.charAt(stringToShift.length()- i - 1);
: it looks buggy and a quick test seems to support that.
$endgroup$
– Peter Taylor
Dec 13 '16 at 15:50
$begingroup$
oh sorry didn't notice that, i'll fix that quick
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 18:33
$begingroup$
I have to agree with @PeterTaylor. When you start writing you own code instead of using the libraries, you should get faster and not slower, especial if it get harder to read your code in the end.
$endgroup$
– mheinzerling
Dec 14 '16 at 6:07
1
1
$begingroup$
This takes time
Omega(mn)
where m
is the displacement of the shift and n
is the length of the string. It's possible to do it in O(n)
.$endgroup$
– Peter Taylor
Dec 13 '16 at 15:03
$begingroup$
This takes time
Omega(mn)
where m
is the displacement of the shift and n
is the length of the string. It's possible to do it in O(n)
.$endgroup$
– Peter Taylor
Dec 13 '16 at 15:03
$begingroup$
I just wrote how to write better, more understandable code rather than efficient
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 15:18
$begingroup$
I just wrote how to write better, more understandable code rather than efficient
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 15:18
$begingroup$
I disagree that it's better to replace a linear algorithm with a quadratic one unless you're massively reducing the constant factor. I'm not really convinced that this code is more understandable either. I can't understand the indexing in
char temporaryChar = stringToShift.charAt(stringToShift.length()- i - 1);
: it looks buggy and a quick test seems to support that.$endgroup$
– Peter Taylor
Dec 13 '16 at 15:50
$begingroup$
I disagree that it's better to replace a linear algorithm with a quadratic one unless you're massively reducing the constant factor. I'm not really convinced that this code is more understandable either. I can't understand the indexing in
char temporaryChar = stringToShift.charAt(stringToShift.length()- i - 1);
: it looks buggy and a quick test seems to support that.$endgroup$
– Peter Taylor
Dec 13 '16 at 15:50
$begingroup$
oh sorry didn't notice that, i'll fix that quick
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 18:33
$begingroup$
oh sorry didn't notice that, i'll fix that quick
$endgroup$
– Erlandas Aksomaitis
Dec 13 '16 at 18:33
$begingroup$
I have to agree with @PeterTaylor. When you start writing you own code instead of using the libraries, you should get faster and not slower, especial if it get harder to read your code in the end.
$endgroup$
– mheinzerling
Dec 14 '16 at 6:07
$begingroup$
I have to agree with @PeterTaylor. When you start writing you own code instead of using the libraries, you should get faster and not slower, especial if it get harder to read your code in the end.
$endgroup$
– mheinzerling
Dec 14 '16 at 6:07
|
show 1 more comment
$begingroup$
fun getShiftedString(s: String, leftShifts: Int, rightShifts: Int): String {
val shift = leftShifts - rightShifts
return when (shift) {
0 -> s
else -> {
val strBuilder = StringBuilder(s)
s.indices.forEach { index ->
val newShift = if (shift > 0) s.length - shift else -shift
val newIndex = (index + newShift).absoluteValue % s.length
strBuilder[newIndex] = s[index]
}
strBuilder.toString()
}
}
}
New contributor
$endgroup$
add a comment |
$begingroup$
fun getShiftedString(s: String, leftShifts: Int, rightShifts: Int): String {
val shift = leftShifts - rightShifts
return when (shift) {
0 -> s
else -> {
val strBuilder = StringBuilder(s)
s.indices.forEach { index ->
val newShift = if (shift > 0) s.length - shift else -shift
val newIndex = (index + newShift).absoluteValue % s.length
strBuilder[newIndex] = s[index]
}
strBuilder.toString()
}
}
}
New contributor
$endgroup$
add a comment |
$begingroup$
fun getShiftedString(s: String, leftShifts: Int, rightShifts: Int): String {
val shift = leftShifts - rightShifts
return when (shift) {
0 -> s
else -> {
val strBuilder = StringBuilder(s)
s.indices.forEach { index ->
val newShift = if (shift > 0) s.length - shift else -shift
val newIndex = (index + newShift).absoluteValue % s.length
strBuilder[newIndex] = s[index]
}
strBuilder.toString()
}
}
}
New contributor
$endgroup$
fun getShiftedString(s: String, leftShifts: Int, rightShifts: Int): String {
val shift = leftShifts - rightShifts
return when (shift) {
0 -> s
else -> {
val strBuilder = StringBuilder(s)
s.indices.forEach { index ->
val newShift = if (shift > 0) s.length - shift else -shift
val newIndex = (index + newShift).absoluteValue % s.length
strBuilder[newIndex] = s[index]
}
strBuilder.toString()
}
}
}
New contributor
New contributor
answered 9 mins ago
leagmainleagmain
1
1
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f149749%2fcircular-shift-string%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
$begingroup$
assuming that the String is at most 50 characters is dangerous.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
$begingroup$
You should add an example to your question.
$endgroup$
– MrSmith42
Dec 13 '16 at 12:57
1
$begingroup$
(The example still looks off in rev. 3: how did the
o
andll
swap places?) What aboutstring.substring(shifts) + string.substring(0, shifts)
?$endgroup$
– greybeard
Dec 13 '16 at 14:04
$begingroup$
("backticks" are for inline code snippets; there is a {}-button and a keyboard shortcut (
<Ctrl>+k
) in the edit-window to turn the selection into a code block (prefixing every line with four additional spaces if the selection doesn't already look like this (then it removes four spaces from the start of every line).))$endgroup$
– greybeard
Dec 13 '16 at 21:45
$begingroup$
@greybeard..You are right.I was using the wrong way to do it.Hello->oHell->loHel->lloHe.Can you suggest the correct way?
$endgroup$
– Javasamurai
Dec 14 '16 at 6:29