I want the last character from a string
I've got str.[str.Length - 1], but that's ugly. There must be a better way.
There's no better way to do it - what you have is fine.
If you really plan to do it a lot, you can author an F# extension property on the string type:
let s = "food"
type System.String with
member this.Last =
this.Chars(this.Length-1) // may raise an exception
printfn "%c" s.Last
This could be also handy:
let s = "I am string"
let lastChar = s |> Seq.last
Result:
val lastChar : char = 'g'
(This is old question), someone might find this useful, orig answer from Brian.
type System.String with
member this.Last() =
if this.Length > 1 then
this.Chars(this.Length - 1).ToString()
else
this.[0].ToString()
member this.Last(n:int) =
let absn = Math.Abs(n)
if this.Length > absn then
let nn =
let a = if absn = 0 then 1 else absn
let b = this.Length - a
if b < 0 then 0 else b
this.Chars(nn).ToString()
else
this.[0].ToString()
"ABCD".Last() -> "D"
"ABCD".Last(1) -> "D"
"ABCD".Last(-1) -> "D"
"ABCD".Last(2) -> "C"
You could also treat it as a sequence, but I'm not sure if that's any more or less ugly than the solution you have:
Seq.nth (Seq.length str - 1) str
Related
I have a string "PIXEL STUDIOS - TEST1" My code works until I reach the first space in the string.
var str = label.stringValue
let c = str.characters
let r = c.index(c.startIndex, offsetBy: 6)..<c.index(c.endIndex, offsetBy: 0)
let substring = str[r]
print(substring)
When I run my code and offsetBy 5 it works but when I try to offset past that point I get the error. Is there something else I need to do to handle spaces in my string?
Your code is working with the given string:
var str = "PIXEL STUDIOS - TEST1"
let c = str.characters
let r = c.index(c.startIndex, offsetBy: 6)..<c.index(c.endIndex, offsetBy: 0)
let substring = str[r]
print(substring)
prints:
STUDIOS - TEST1
Conclusion: label.stringValue is fishy.
Print it out for further investigations.
I want to read a line from a file, initialize an array from that line and then display the integers.
Why is is not reading the five integers in the line? I want to get output 1 2 3 4 5, i have 1 1 1 1 1
open Array;;
open Scanf;;
let print_ints file_name =
let file = open_in file_name in
let s = input_line(file) in
let n = ref 5 in
let arr = Array.init !n (fun i -> if i < !n then sscanf s "%d" (fun a -> a) else 0) in
let i = ref 0 in
while !i < !n do
print_int (Array.get arr !i);
print_string " ";
i := !i + 1;
done;;
print_ints "string_ints.txt";;
My file is just: 1 2 3 4 5
You might want to try the following approach. Split your string into a list of substrings representing numbers. This answer describes one way of doing so. Then use the resulting function in your print_ints function.
let ints_of_string s =
List.map int_of_string (Str.split (Str.regexp " +") s)
let print_ints file_name =
let file = open_in file_name in
let s = input_line file in
let ints = ints_of_string s in
List.iter (fun i -> print_int i; print_char ' ') ints;
close_in file
let _ = print_ints "string_ints.txt"
When compiling, pass str.cma or str.cmxa as an argument (see this answer for details on compilation):
$ ocamlc str.cma print_ints.ml
Another alternative would be using the Scanf.bscanf function -- this question, contains an example (use with caution).
The Scanf.sscanf function may not be particularly suitable for this task.
An excerpt from the OCaml manual:
the scanf facility is not intended for heavy duty lexical analysis and parsing. If it appears not expressive enough for your needs, several alternative exists: regular expressions (module Str), stream parsers, ocamllex-generated lexers, ocamlyacc-generated parsers
There is though a way to parse a string of ints using Scanf.sscanf (which I wouldn't recommend):
let rec int_list_of_string s =
try
Scanf.sscanf s
"%d %[0-9-+ ]"
(fun n rest_str -> n :: int_list_of_string rest_str)
with
| End_of_file | Scanf.Scan_failure _ -> []
The trick here is to represent the input string s as a part which is going to be parsed into a an integer (%d) and the rest of the string using the range format: %[0-9-+ ]", which will match the rest of the string, containing only decimal digits 0-9, the - and + signs, and whitespace .
This is a question from one of the online coding challenge (which has completed).
I just need some logic for this as to how to approach.
Problem Statement:
We have two strings A and B with the same super set of characters. We need to change these strings to obtain two equal strings. In each move we can perform one of the following operations:
1. swap two consecutive characters of a string
2. swap the first and the last characters of a string
A move can be performed on either string.
What is the minimum number of moves that we need in order to obtain two equal strings?
Input Format and Constraints:
The first and the second line of the input contains two strings A and B. It is guaranteed that the superset their characters are equal.
1 <= length(A) = length(B) <= 2000
All the input characters are between 'a' and 'z'
Output Format:
Print the minimum number of moves to the only line of the output
Sample input:
aab
baa
Sample output:
1
Explanation:
Swap the first and last character of the string aab to convert it to baa. The two strings are now equal.
EDIT : Here is my first try, but I'm getting wrong output. Can someone guide me what is wrong in my approach.
int minStringMoves(char* a, char* b) {
int length, pos, i, j, moves=0;
char *ptr;
length = strlen(a);
for(i=0;i<length;i++) {
// Find the first occurrence of b[i] in a
ptr = strchr(a,b[i]);
pos = ptr - a;
// If its the last element, swap with the first
if(i==0 && pos == length-1) {
swap(&a[0], &a[length-1]);
moves++;
}
// Else swap from current index till pos
else {
for(j=pos;j>i;j--) {
swap(&a[j],&a[j-1]);
moves++;
}
}
// If equal, break
if(strcmp(a,b) == 0)
break;
}
return moves;
}
Take a look at this example:
aaaaaaaaab
abaaaaaaaa
Your solution: 8
aaaaaaaaab -> aaaaaaaaba -> aaaaaaabaa -> aaaaaabaaa -> aaaaabaaaa ->
aaaabaaaaa -> aaabaaaaaa -> aabaaaaaaa -> abaaaaaaaa
Proper solution: 2
aaaaaaaaab -> baaaaaaaaa -> abaaaaaaaa
You should check if swapping in the other direction would give you better result.
But sometimes you will also ruin the previous part of the string. eg:
caaaaaaaab
cbaaaaaaaa
caaaaaaaab -> baaaaaaaac -> abaaaaaaac
You need another swap here to put back the 'c' to the first place.
The proper algorithm is probably even more complex, but you can see now what's wrong in your solution.
The A* algorithm might work for this problem.
The initial node will be the original string.
The goal node will be the target string.
Each child of a node will be all possible transformations of that string.
The current cost g(x) is simply the number of transformations thus far.
The heuristic h(x) is half the number of characters in the wrong position.
Since h(x) is admissible (because a single transformation can't put more than 2 characters in their correct positions), the path to the target string will give the least number of transformations possible.
However, an elementary implementation will likely be too slow. Calculating all possible transformations of a string would be rather expensive.
Note that there's a lot of similarity between a node's siblings (its parent's children) and its children. So you may be able to just calculate all transformations of the original string and, from there, simply copy and recalculate data involving changed characters.
You can use dynamic programming. Go over all swap possibilities while storing all the intermediate results along with the minimal number of steps that took you to get there. Actually, you are going to calculate the minimum number of steps for every possible target string that can be obtained by applying given rules for a number times. Once you calculate it all, you can print the minimum number of steps, which is needed to take you to the target string. Here's the sample code in JavaScript, and its usage for "aab" and "baa" examples:
function swap(str, i, j) {
var s = str.split("");
s[i] = str[j];
s[j] = str[i];
return s.join("");
}
function calcMinimumSteps(current, stepsCount)
{
if (typeof(memory[current]) !== "undefined") {
if (memory[current] > stepsCount) {
memory[current] = stepsCount;
} else if (memory[current] < stepsCount) {
stepsCount = memory[current];
}
} else {
memory[current] = stepsCount;
calcMinimumSteps(swap(current, 0, current.length-1), stepsCount+1);
for (var i = 0; i < current.length - 1; ++i) {
calcMinimumSteps(swap(current, i, i + 1), stepsCount+1);
}
}
}
var memory = {};
calcMinimumSteps("aab", 0);
alert("Minimum steps count: " + memory["baa"]);
Here is the ruby logic for this problem, copy this code in to rb file and execute.
str1 = "education" #Sample first string
str2 = "cnatdeiou" #Sample second string
moves_count = 0
no_swap = 0
count = str1.length - 1
def ends_swap(str1,str2)
str2 = swap_strings(str2,str2.length-1,0)
return str2
end
def swap_strings(str2,cp,np)
current_string = str2[cp]
new_string = str2[np]
str2[cp] = new_string
str2[np] = current_string
return str2
end
def consecutive_swap(str,current_position, target_position)
counter=0
diff = current_position > target_position ? -1 : 1
while current_position!=target_position
new_position = current_position + diff
str = swap_strings(str,current_position,new_position)
# p "-------"
# p "CP: #{current_position} NP: #{new_position} TP: #{target_position} String: #{str}"
current_position+=diff
counter+=1
end
return counter,str
end
while(str1 != str2 && count!=0)
counter = 1
if str1[-1]==str2[0]
# p "cross match"
str2 = ends_swap(str1,str2)
else
# p "No match for #{str2}-- Count: #{count}, TC: #{str1[count]}, CP: #{str2.index(str1[count])}"
str = str2[0..count]
cp = str.rindex(str1[count])
tp = count
counter, str2 = consecutive_swap(str2,cp,tp)
count-=1
end
moves_count+=counter
# p "Step: #{moves_count}"
# p str2
end
p "Total moves: #{moves_count}"
Please feel free to suggest any improvements in this code.
Try this code. Hope this will help you.
public class TwoStringIdentical {
static int lcs(String str1, String str2, int m, int n) {
int L[][] = new int[m + 1][n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0)
L[i][j] = 0;
else if (str1.charAt(i - 1) == str2.charAt(j - 1))
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = Math.max(L[i - 1][j], L[i][j - 1]);
}
}
return L[m][n];
}
static void printMinTransformation(String str1, String str2) {
int m = str1.length();
int n = str2.length();
int len = lcs(str1, str2, m, n);
System.out.println((m - len)+(n - len));
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String str1 = scan.nextLine();
String str2 = scan.nextLine();
printMinTransformation("asdfg", "sdfg");
}
}
Could someone help me to write a function that checks if a string is a substring of another string?
(there can be more than only 2 strings)
Thanks
With String module:
let contains s1 s2 =
try
let len = String.length s2 in
for i = 0 to String.length s1 - len do
if String.sub s1 i len = s2 then raise Exit
done;
false
with Exit -> true
With Str module, like #barti_ddu said check this topic:
let contains s1 s2 =
let re = Str.regexp_string s2 in
try
ignore (Str.search_forward re s1 0);
true
with Not_found -> false
With Batteries, you can use String.exists. It also exists in ExtLib: String.exists.
A String-based alternative to cago's answer that might have better performance and lower memory usage:
let is_substring string substring =
let ssl = String.length substring and sl = String.length string in
if ssl = 0 || ssl > sl then false else
let max = sl - ssl and clone = String.create ssl in
let rec check pos =
pos <= max && (
String.blit string pos clone 0 ssl ; clone = substring
|| check (String.index_from string (succ pos) substring.[0])
)
in
try check (String.index string substring.[0])
with Not_found -> false
String str="hello world";
System.out.println(str.contains("world"));//true
System.out.println(str.contains("world1"));//false
To learn the basics of OCaml, I'm solving one of the easy facebook engineering puzzles using it. Essentially, I'd like to do something like the following Python code:
some_str = some_str.strip()
That is, I'd like to strip all of the whitespace from the beginning and the end. I don't see anything obvious to do this in the OCaml Str library. Is there any easy way to do this, or am I going to have to write some code to do it (which I wouldn't mind, but would prefer not to :) ).
Bear in mind that I'm limited to what's in the libraries that come with the OCaml distribution.
I know this question is uber-old, but I was just pondering the same thing and came-up with this (from toplevel):
let strip str =
let str = Str.replace_first (Str.regexp "^ +") "" str in
Str.replace_first (Str.regexp " +$") "" str;;
val strip : string -> string = <fun>
then
strip " Hello, world! ";;
- : string = "Hello, world!"
UPDATE:
As of 4.00.0, standard library includes String.trim
It is really a mistake to limit yourself to the standard library, since the standard ilbrary is missing a lot of things. If, for example, you were to use Core, you could simply do:
open Core.Std
let x = String.strip " foobar "
let () = assert (x = "foobar")
You can of course look at the sources of Core if you want to see the implementation. There is a similar function in ExtLib.
how about
let trim str =
if str = "" then "" else
let search_pos init p next =
let rec search i =
if p i then raise(Failure "empty") else
match str.[i] with
| ' ' | '\n' | '\r' | '\t' -> search (next i)
| _ -> i
in
search init
in
let len = String.length str in
try
let left = search_pos 0 (fun i -> i >= len) (succ)
and right = search_pos (len - 1) (fun i -> i < 0) (pred)
in
String.sub str left (right - left + 1)
with
| Failure "empty" -> ""
(Via Code Codex)
I believe at the point when the other answers were given, version 4.00 was not out yet. Actually, in OCaml 4.00, there is a String.trim function in the string module to trim leading and trailing white spaces.
Alternatively, if you're restricted to an older version of OCaml, you may use this function that is shamelessly copied from the source of 4.00's string module.
let trim s =
let is_space = function
| ' ' | '\012' | '\n' | '\r' | '\t' -> true
| _ -> false in
let len = String.length s in
let i = ref 0 in
while !i < len && is_space (String.get s !i) do
incr i
done;
let j = ref (len - 1) in
while !j >= !i && is_space (String.get s !j) do
decr j
done;
if !i = 0 && !j = len - 1 then
s
else if !j >= !i then
String.sub s !i (!j - !i + 1)
else
""
;;
Something simple like this should work fine:
#require "str";;
let strip_string s =
Str.global_replace (Str.regexp "[\r\n\t ]") "" s
Standard library's
String.trim
does exactly that.