I'm trying to select a random element in an attribute, and then reverse the value of that randomly selected element between 0 and n, and then reprint the whole attribute again, with the reversed element shown. The reverse value for 0 is 1, and for 1 is 0 in this case.
Here is what I've attempted:
String whatever = "11111";
int n = whatever.length();
//the UI class generates a random integer number between 0 and n
int p = CS2004.UI(0,n);
if (whatever.charAt(p)=='0') {
+= 1;
} else {
+= 0;
}
I'm lost on the adding the opposite number bit.
I should clarify that this is homework!
Strings are immutable in Java, but you could do
StringBuilder sb = new StringBuilder(whatever);
if (whatever.charAt(p)=='0') {
sb.setCharAt(p, '1');
} else {
sb.setCharAt(p, '0');
}
whatever = sb.toString();
OK, lets give this a try.
Firstly, you will need to change the name of your variable 5 - I don't think you're allowed to start variables with a number (see here)
I'm assuming that by 'attribute' you mean the length of the String? This is probably supposed to be the value of your 5 variable.
So, lets look at some modified code...
String whatever = "11111";
int n = whatever.length();
//the UI class generates a random integer number between 0 and n
int p = CS2004.UI(0,n);
StringBuilder sb = new StringBuilder(whatever);
if (whatever.charAt(p)=='0') {
sb.setCharAt(p, '1');
} else {
sb.setCharAt(p, '0');
}
whatever = sb.toString();
This code will change the value of the character in position p, and then convert it back to a String.
Basic StringBuilder usage with a ternary operator produces what you're looking for:
StringBuilder result = new StringBuilder();
result.append(whatever.substring(0, p));
result.append(whatever.charAt(p) == '0' ? "1" : "0");
result.append(whatever.substring(p + 1, whatever.length()));
System.out.println("Result = " + result.toString());
As others have noted, using the StringBuilder.setCharAt() method produces a more concise answer (with the ternary operator added, this is the shortest answer so far):
StringBuilder result = new StringBuilder(whatever);
result.setCharAt(p, whatever.charAt(p) == '0' ? '1' : '0');
System.out.println("Result = " + result.toString());
Strings in Java are immutable so you need to first convert them to some mutable structure before modifying them.
If you are trying to flip the characters at some position in a code then this code might be of help :
String whatever = "11111";
char[] charArray = whatever.toCharArray();
int n = whatever.length();
//the UI class generates a random integer number between 0 and n
int p = CS2004.UI(0,n);
if (charArray[p]=='0') {
charArray[p] = 1;
} else {
charArray[p] = 0;
}
Then you can modify whatever characters you wish to. Once you are done you can reconstruct a String from the charArray as follows :
String result = new String(charArray);
This can also be achieved using StringBuilder.
Related
I'm working on an a problem trying to generate all the possible combination between two chars based on early generated combine using java 8
for example :
private static final String LETTER_RANGE = "abcdefghijklmnopqrstuvwxz";
from this letter rang I want to extract all differents combine between two chars XX
for example :
zz,zx,zw....za
xz,xx,xw....xa
..,..,..,..,..
az,ax,aw... aa
My problem is I need to generate those combination at runtime based on previous combine :
String value = generate("zx") // this should return 'zw'
Can any one helpe me on any idea how can use java 8 loops,Stream,String to do this Thanks in advance
You can use simple character arithmetics. As chars can be incremented and compared:
final List<String> permutations = new ArrayList<>(26 * 26);
for (char[] array = {'a', 'a'}; array[0] <= 'z'; array[0]++) {
for (array[1] = 'a'; array[1] <= 'z'; array[1]++) {
permutations.add(new String(array));
}
}
This piece of code creates every combination of all characters between a and z inclusive and adds them to a List.
This is possible because in ASCII the character value of a (97) is smaller than the one from z (122).
I've also used some optimizations, like the use of an array inside the for-loop to hold the current combination of 2 chars. This array can then also be directly used to create a new string, with the string constructor: String(char[]).
Tools one might use are:
char ch = LETTER_RANGE.charAt(2); // 'c'
int ix = LETTER_RANGE.indexOf(ch); // 2
Using the single char[] array is probably much easier, so the method might look like:
String next(String combination) {
char[] chars = combination.toCharArray();
char ch = chars[1];
if (...) {
}
return new String(chars);
}
Sounds like very bad solution of task for me. But if you really need it, it can be done like this.
private static final String LETTER_RANGE = "abcdefghijklmnopqrstuvwxz";
public String findNext(String prev) {
if(prev==null || prev.length()<2)
throw new RuntimeException("Invalid argument");
int char1Index = LETTER_RANGE.indexOf(prev.charAt(0));
int char2Index = LETTER_RANGE.indexOf(prev.charAt(1));
char2Index--;
if (char2Index < 0) {
char1Index--;
char2Index = LETTER_RANGE.length() - 1;
}
if (char1Index < 0) {
return null;// or what you need here.
}
return new String(new char[]{LETTER_RANGE.charAt(char1Index), LETTER_RANGE.charAt(char2Index)});
}
And the task find all Concatenation between two chars from predefined list I would do like this
public List findAll() {
List<String> result=new ArrayList<>();
char[] chars=LETTER_RANGE.toCharArray();
for(int i=0;i<chars.length;i++)
for(int j=0;j<chars.length;j++)
result.add(new String(new char[]{chars[i],chars[j]}));
return result;
}
The pattern in your example reminds me of Excel columns. Excel names its columns with letters from A to Z, and then the sequence goes AA, AB, AC... AZ, BA, BB, etc. So if we interpret your combinations as Excel column titles the task could be reworded to:
Given a column title as appears in an Excel sheet, find the next
column title (or previous as shown in your expected output).
To do this you can write a method that accepts a string as a parameter (like "zf") and returns the actual column number. And then add or substract 1 to get the number of the next or previos column and convert the number back to string. Example:
public final class ExcelColumn {
public static void main(String[] args) {
String str = "zx";
System.out.println(getPreviousColumn(str));
}
public static int toColumnNumber(String column) {
int result = 0;
for (int i = 0; i < column.length(); i++) {
result *= 26;
result += column.charAt(i) - 'a' + 1;
}
return result;
}
public static String toColumnName(int number) {
final StringBuilder sb = new StringBuilder();
int num = number - 1;
while (num >= 0) {
int numChar = (num % 26) + 97;
sb.append((char)numChar);
num = (num / 26) - 1;
}
return sb.reverse().toString();
}
public static String getNextColumn(String s) {
return toColumnName( toColumnNumber(s)+1);
}
public static String getPreviousColumn(String s) {
return toColumnName( toColumnNumber(s)-1);
}
}
ToDo:
Input validiation and
exception handling
Pros:
You can use this even if your combined string length is > 2
can be easily modified to use with uppercase letters
You can do something like from 'be' to 'cf' to generate all combinations which fall in this range if necessary
Cons:
May be to much code for a simple task. Look at #Andrii Vdovychenko's
comment which solves the problem in few lines
I'm having performance issues. Does anyone have a faster/better solution for doing the following:
String main = "";
for (String proposition : propositions) {
if (main.length() == 0) {
main = proposition;
} else {
main = "|(" + proposition + "," + main + ")";
}
}
I know concat and stringbuilder are faster, but i don't see how i can use these methods. Because of the following line of code:
main = "|(" + proposition + "," + main + ")";
Thanks in advance!
So from what I can tell there are 3 problems here:
Values are primarily prepended to the string.
For each value a character is appended.
If only one value is present, nothing should be appended or prepended.
With 2 or more items, the 0th item is handled differently:
0:""
1:"A"
2:"|(B,A)"
3:"|(C,|(B,A))"
It can be made quicker by making a few changes:
Reverse the algorithm, this means the majority of the work involves appending, allowing you to use StringBuilders.
Count the number of closing )'s and append those after the loop is finished.
Special case for 0 or 1 items in the list.
With those changes the algorithm should be able to use a StringBuilder and be a lot quicker.
Attempt at an algorithm:
int length = propositions.size();
if (length == 0) {
main = "";
} else {
StringBuilder sb = new StringBuilder();
int nestingDepth = 0;
// Reverse loop, ignoring 0th element due to special case
for (int i = length - 1; i > 0; i--) {
sb.append("|(").append(propositions.get(i)).append(',');
nestingDepth++;
}
// Append last element due to special casing
sb.append(propositions.get(0));
for (int i = 0; i < nestingDepth; i++) {
sb.append(')');
}
main = sb.toString();
}
I believe this should produce the correct results, but it should give the right idea.
The problem is that you're prepending and appending to the string as you go. String and StringBuilder dont handle this well (and give quadratic performance). But you can use a dequeue which supports insertion at start and end to store all the pieces. Then finally you can join the bits in the dequeue.
ArrayDeque bits = new ArrayDeque();
for (String proposition : propositions) {
if (bits.size() == 0) {
bits.push(proposition);
} else {
// Add prefix
main.offerFirst("|(" + proposition + "," );
// Add suffix
main.push(")");
}
}
StringBuilder sb = new StringBuilder();
for( String s : bits) {
sb.append(s);
}
main = sb.toString();
Assuming this is an array of propositions, you could first sum the length of the String(s) in the array. Add 4 for your additional characters, and subtract 4 because you don't use those separators on the first element. That should be the perfect size for your output (this is optional, because StringBuilder is dynamically sized). Next, construct a StringBuilder. Add the first element. All subsequent elements follow the same pattern, so the loop is simplified with a traditional for. Something like,
int len = Stream.of(propositions).mapToInt(s -> s.length() + 4).sum() - 4;
StringBuilder sb = new StringBuilder(len); // <-- len is optional
sb.append(propositions[0]);
for (int i = 1; i < propositions.length; i++) {
sb.insert(0, ",").insert(0, propositions[i]).insert(0, "|(").append(")");
}
System.out.println(sb);
I'm getting in an int with a 6 digit value. I want to display it as a String with a decimal point (.) at 2 digits from the end of int. I wanted to use a float but was suggested to use String for a better display output (instead of 1234.5 will be 1234.50). Therefore, I need a function that will take an int as parameter and return the properly formatted String with a decimal point 2 digits from the end.
Say:
int j= 123456
Integer.toString(j);
//processing...
//output : 1234.56
As mentioned in comments, a StringBuilder is probably a faster implementation than using a StringBuffer. As mentioned in the Java docs:
This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.
Usage :
String str = Integer.toString(j);
str = new StringBuilder(str).insert(str.length()-2, ".").toString();
Or if you need synchronization use the StringBuffer with similar usage :
String str = Integer.toString(j);
str = new StringBuffer(str).insert(str.length()-2, ".").toString();
int j = 123456;
String x = Integer.toString(j);
x = x.substring(0, 4) + "." + x.substring(4, x.length());
int yourInteger = 123450;
String s = String.format("%6.2f", yourInteger / 100.0);
System.out.println(s);
Using ApacheCommons3 StringUtils, you could also do
int j = 123456;
String s = Integer.toString(j);
int pos = s.length()-2;
s = StringUtils.overlay(s,".", pos, pos);
it's basically substring concatenation but shorter if you don't mind using libraries, or already depending on StringUtils
In most use-cases, using a StringBuilder (as already answered) is a good way to do this. However, if performance matters, this may be a good alternative.
/**
* Insert the 'insert' String at the index 'position' into the 'target' String.
*
* ````
* insertAt("AC", 0, "") -> "AC"
* insertAt("AC", 1, "xxx") -> "AxxxC"
* insertAt("AB", 2, "C") -> "ABC
* ````
*/
public static String insertAt(final String target, final int position, final String insert) {
final int targetLen = target.length();
if (position < 0 || position > targetLen) {
throw new IllegalArgumentException("position=" + position);
}
if (insert.isEmpty()) {
return target;
}
if (position == 0) {
return insert.concat(target);
} else if (position == targetLen) {
return target.concat(insert);
}
final int insertLen = insert.length();
final char[] buffer = new char[targetLen + insertLen];
target.getChars(0, position, buffer, 0);
insert.getChars(0, insertLen, buffer, position);
target.getChars(position, targetLen, buffer, position + insertLen);
return new String(buffer);
}
For Kotlin dudes ;) from the accepted answer (#MikeThomsen's)
fun String.insert(insertAt: Int, string: String): String {
return this.substring(0, insertAt) + string + this.substring(insertAt, this.length)
}
Test ✅
"ThisTest".insert(insertAt = 4, string = "Is").should.equal("ThisIsTest")
String.format("%0d.%02d", d / 100, d % 100);
You could use
System.out.printf("%4.2f%n", ((float)12345)/100));
As per the comments, 12345/100.0 would be better, as would the use of double instead of float.
If you are using a system where float is expensive (e.g. no FPU) or not allowed (e.g. in accounting) you could use something like this:
for (int i = 1; i < 100000; i *= 2) {
String s = "00" + i;
System.out.println(s.substring(Math.min(2, s.length() - 2), s.length() - 2) + "." + s.substring(s.length() - 2));
}
Otherwise the DecimalFormat is the better solution. (the StringBuilder variant above won't work with small numbers (<100)
I think a simpler and more elegant solution to insert a String in a certain position would be this one-liner:
target.replaceAll("^(.{" + position + "})", "$1" + insert);
For example, to insert a missing : into a time String:
"-0300".replaceAll("^(.{3})", "$1:");
What it does is, matches position characters from the beginning of the string, groups that, and replaces the group with itself ($1) followed by the insert string. Mind the replaceAll, even though there's always one occurrence, because the first parameter must be a regex.
Of course it does not have the same performance as the StringBuilder solution, but I believe the succinctness and elegance as a simple and easier to read one-liner (compared to a huge method) is sufficient for making it the preferred solution in most non performance-critical use-cases.
Note I'm solving the generic problem in the title for documentation reasons, of course if you are dealing with decimal numbers you should use the domain-specific solutions already proposed.
There are good answers here, but with Kotlin extensions addition we can do it even more simply:
val indexWhereInsertIsIntended = 2
val inputString = "2408"
val resultingString = inputString.toCharArray().toMutableList()
.also {
it.add(indexWhereInsertIsIntended, '/')
}.joinToString("")
Result = 24/08
This example shows a card expiry date, and slash (/) is intended at 2nd Index. So the resulting index in this case will have / at 2nd index.
If you want to replace and not add:
val indexWhereInsertIsIntended = 2
val inputString = "2408"
val resultingString = inputString.toCharArray()
.also {
it[indexWhereInsertIsIntended] = '/'
}.joinToString("")
Result = 24/0
public static void main(String[] args) {
char ch='m';
String str="Hello",k=String.valueOf(ch),b,c;
System.out.println(str);
int index=3;
b=str.substring(0,index-1 );
c=str.substring(index-1,str.length());
str=b+k+c;
}
// Create given String and make with size 30
String str = "Hello How Are You";
// Creating StringBuffer Object for right padding
StringBuffer stringBufferRightPad = new StringBuffer(str);
while (stringBufferRightPad.length() < 30) {
stringBufferRightPad.insert(stringBufferRightPad.length(), "*");
}
System.out.println("after Left padding : " + stringBufferRightPad);
System.out.println("after Left padding : " + stringBufferRightPad.toString());
// Creating StringBuffer Object for right padding
StringBuffer stringBufferLeftPad = new StringBuffer(str);
while (stringBufferLeftPad.length() < 30) {
stringBufferLeftPad.insert(0, "*");
}
System.out.println("after Left padding : " + stringBufferLeftPad);
System.out.println("after Left padding : " + stringBufferLeftPad.toString());
Try this :
public String ConvertMessage(String content_sendout){
//use unicode (004E00650077) need to change to hex (N&#x;0065&#x;0077;) first ;
String resultcontent_sendout = "";
int i = 4;
int lengthwelcomemsg = content_sendout.length()/i;
for(int nadd=0;nadd<lengthwelcomemsg;nadd++){
if(nadd == 0){
resultcontent_sendout = "&#x"+content_sendout.substring(nadd*i, (nadd*i)+i) + ";&#x";
}else if(nadd == lengthwelcomemsg-1){
resultcontent_sendout += content_sendout.substring(nadd*i, (nadd*i)+i) + ";";
}else{
resultcontent_sendout += content_sendout.substring(nadd*i, (nadd*i)+i) + ";&#x";
}
}
return resultcontent_sendout;
}
I'm trying to create a program that reads in two bases from stdin and checks to see what's the smallest number in which both have repeating digits in it. It seems to be working fine for small bases but when I use larger bases I seem to be getting the wrong answer. e.g. giving it 3 and 50 it will find 22 as the smallest number where they both have repeated digits but i'm pretty sure 22 in base 50 is a single number.
What's the logic here that I'm missing? I'm stumped. Anything to point me in the right direction would be appreciated :)
My conversion method, this works for smaller bases but not larger it seems.
public static String converties(int number, int base)
{
int remainder;
ArrayList<Integer>remainders = new ArrayList<Integer>();
while (number != 0)
{
remainder = number%base;
remainders.add(remainder);
number = number/base;
}
String result = "";
for (int i = 0; i < remainders.size(); i++)
{
result+=Integer.toString(remainders.get(i));
}
result = reverseString(result);
return result;
}
public static String reverseString(String result)
{
String newResult = "";
for (int i = result.length()-1; i >= 0; i--)
{
newResult+=result.charAt(i);
}
return newResult;
}
public static boolean areThereRepeats(String value)
{
ArrayList<Character> splitString = new ArrayList<Character>();
for (char c : value.toCharArray())
{
//if it already contains value then theres repeated digit
if (splitString.contains(c))
{
return true;
}
splitString.add(c);
}
return false;
}
The problem is in this function:
public static boolean areThereRepeats(String value){
ArrayList<Character> splitString = new ArrayList<Character>();
for (char c : value.toCharArray()){
//if it already contains value then theres repeated digit
if (splitString.contains(c)){
return true;//Note that returning here only checks the first value that matches
}
splitString.add(c);
}
return false;
}
When you check to see if splitString.contains(c) it will return true if the array is length one. You aren't doing anything to check that the char c you're checking isn't comparing against itself.
Also note that Maraca has a point: the data structure you're choosing to utilize to record your remainders is flawed. areThereRepeats will work fine for checking if you assume that each new character represents a new remainder (or more specifically, the index into the base you're checking of the remainder you found). But why marshal all of that into a string in the first place? Why not pass the ArrayList to areThereRepeats?
public static boolean converties(int number, int base){
int remainder;
ArrayList<Integer>remainders = new ArrayList<Integer>();
while (number != 0){
remainder = number%base;
remainders.add(remainder);//Saves the index of the remainder in the current base, using an integer base-10 representation
number = number/base;
}
return areThereRepeats(remainders);
}
//Recursion ain't efficient, but...
public static boolean areThereRepeats(ArrayList<Integer> remainders){
if (remainders.size() <= 1) {
return false;
}
rSublist = remainders.sublist(1, remainders.size())
if (rSublist.contains(remainders.get(0)) {
return true;
}
return areThereRepeats(rSublist);
}
result+=Integer.toString(remainders.get(i));
In this line you add the remainder in base 10, so it will only work correctly if you find a match with base <= 10. Btw. It could be done very easily with BigInteger (if you don't want to do it yourself).
Otherwise:
result += (char)(remainders.get(i) < 10 ? ('0' + remainders.get(i)) : ('A' + remainders.get(i) - 10));
This will work up to base 36.
Or just use result += (char)remainders.get(i); it will work up to base 256, but it won't be readable.
And I agree with Nathaniel Ford, it would be better to pass the ArrayLists. If you still want to get the String in the standard way you can make another function to which you pass the ArrayList and transform it with the 1st method shown here.
So I was at a programming interview a few months ago and this problem tripped me up for some reason. There are a couple of solutions I can think of but most of them seem extremely inefficient. Though I've been programming in some capacity for years, I'm currently in college for a CS degree so my point of reference may be incomplete. I was hoping someone here might offer up some possible solutions:
"Given a set of strings and associated numerical 'values,' assemble a palindrome from these string whose value (defined by the sum of the strings used to create it) is the highest possible."
There were no limits to how many strings could be provided, some strings may not be used.
Example:
"asd" - 3
"dsa" - 5
"appa" - 1
Result would be "asdappadsa" with a value of 9.
My thought would be to try all strings in all orders, then drop off one, starting with the lowest valued one, but that solution is O(N!) and I'd assume that's not ok.
(Preferred languages are C and Java, but whatever works)
EDIT: Clarification. Each string provided can only be used once, and has to be used exactly as provided, though you may choose to not use any of the strings in your palindrome. You can not use substrings of provided strings, nor can you reverse the string.
Replace "all strings" with "all palindromes" and the problem space becomes much smaller.
Divide the strings into 26 subsets.
Strings beginning with x (for 'a' <= x <= 'z')
[or whatever the set of "letters" is]
Now divide them into another 26 subsets
Strings ending with y ( for 'a' <= y <= 'z')
Note each string appears in a "begins with" set and an "ends with" set.
Use these sets to guide creation of all possible palindromes.
Start with two empty strings: prefix and suffix
for each string in the original set
assign it to the prefix
call recursiveFunction(prefix, suffix)
def recursiveFunction(prefix, suffix):
if prefix + <anything> + suffix cannot form a palindrome return
if prefix + suffix is a palindrome, remember it
while you have unused strings
if the suffix is shorter than the prefix
Look at the first unmatched character in the prefix
for each unused string that ends in that character
call recursiveFunction(prefix, string + suffix)
else if prefix is shorter than suffix
look at the last unmatched character in the suffix
for each unused string that ends with that character
call recursiveFunction(prefix + string, suffix)
else // suffix and prefix have equal lenghths
for each unused string
call recursiveFunction(prefix + string, suffix)
Be sure to mark the string used in both begins with and ends when you use it.
And be sure to consider the impact of recursion on the "used" marker.
Then pick the palindrome with the best score.
With palindrones, you can split the string into 3 substrings, ABC. There is potential within the set to find string reversals, so when you get a hit you can keep track of these strings for useage in substring A and C. If you don't get a reversal hit within the entire set, you just need to find the largest string (or string with the highest value) that is a reflection of itself. Not the best solution, I'm sure, but I did it for fun anyways so I may as well share. Also, I made no efforts to make this code "clean", so its a bit ugly, but it works.
public class Main {
private static String[] set = new String[] { "asdf" , "kjdij", "skjdihi", "ddidid" , "ididid", "iddid", "oihu", "uhio", "fdsa", "ajsja" };
public static void main(String[] args){
//Used for a couple of for loops...
int count;
Map<String, String> map = new HashMap<String,String>(); //Hold the strings and their reversals in a hashmap for quick lookups.
/* Think of the palindrome as 3 substrings, A, B, and C. */
ArrayList<String> A = new ArrayList<String>();
ArrayList<String> B = new ArrayList<String>();
ArrayList<String> C = new ArrayList<String>();
count = set.length;
String[] reverse_set = new String[count];
for(int x = 0; x < count; x++){
String reverse = new StringBuilder(set[x]).reverse().toString();
/* Check strings that would work for section B, since it's a set, we know that if it could work for B,
* it couldn't work for A or C - since a set contains no duplicates. */
if(reverse.equals(set[x])){
B.add(set[x]);
} else {
/* Otherwise, we'll have to check to see if it would work for A and C */
reverse_set[x] = reverse;
map.put(set[x], reverse);
}
}
/* Check the map for reverse string hits, we know that if another string exists in set S such that S(X) == R(X) it can work for substring
* A and C. */
int map_size = map.size();
int hit_count = 0;
for(int i = 0; i < map_size; i++){
String s = map.get(reverse_set[i]);
if(s != null){
hit_count++;
A.add(set[i]);
C.add(reverse_set[i]);
map.remove(set[i]); //remove the reflection, so we don't get duplicates
}
}
/* Find the longest string in B, since we'll have to do this even if was had any hits in the previous loop. */
String b = null;
if(B.size() > 0){
int length = 0;
for(String x : B){
int mLength = x.length();
if(mLength > length){
b = x;
length = mLength;
}
}
}
/* Build the palinedrome */
String palineString = "";
if(hit_count == 0 && b != null){
palineString = b;
} else {
for(String x : A){
palineString += x;
}
if(b != null){
palineString += b;
}
count = C.size();
for(int y = (count - 1); y >= 0; y--){
palineString += C.get(y);
}
}
if(checkPalindrome(palineString)){
System.out.print("The Palindrone is: " + palineString + " Score: " + Integer.toString(palineString.length()));
} else {
System.out.print("Oops...");
}
}
private static boolean checkPalindrome(String x){
if(x.equals(new StringBuilder(x).reverse().toString())){
return true;
} else {
return false;
}
}
}
Output:
The Palindrone is: asdfoihuajsjauhiofdsa Score: 21
EDIT:
Note: for the time being, I used the string's length as the "assigned value", I'll make an edit later to account for assigning random values to strings, but it won't make too much of a difference, since it only adds a few extra use cases to check for.